1 -00:00:00,485 --> 00:00:05,515 Translated by visionNoob, KNU https://github.com/insurgent92/CS231N_17_KOR_SUB 2 00:00:08,355 --> 00:00:11,357 자 12시가 지났군요 시작합니다. 3 00:00:14,644 --> 00:00:17,419 우선 지난시간에 배운 내용을 복습하겠습니다. 4 00:00:17,419 --> 00:00:23,400 지난시간에 Nerural networks를 학습 시킬 때 필요한 여러가지 중요한 것들을 배웠습니다. 5 00:00:23,400 --> 00:00:30,439 지난 시간에 배운 내용을 다시 한번 살펴 본 뒤에 몇 가지 더 배워보겠습니다. 6 00:00:30,439 --> 00:00:34,707 우선 공지사항을 몇 가지 전달합니다. 7 00:00:34,707 --> 00:00:39,645 우선 과제 1의 마감기한이 종료되었습니다. 여러분 모두 잘 제출했길 바랍니다. 8 00:00:39,645 --> 00:00:57,322 다들 잘 했나요? 과제 1은 체점 중에 있습니다. 9 00:00:57,322 --> 00:01:04,121 그리고 두 번째는 프로젝트 제안서 제출은 금일 11:59 PM 까지 입니다. 10 00:01:04,959 --> 00:01:09,074 오늘 까지 꼭 제출 해 주시기 바랍니다. 자세한 사항은 web과 Piazza에서 확인바랍니다. 11 00:01:09,074 --> 00:01:15,269 그리고 과제 2가 나왔습니다. 제출까지 1주일정도의 기간이 남았습니다. 12 00:01:15,269 --> 00:01:25,860 과제 2는 우리 수업에서 가장 오래 걸리는 과제 입니다. 그러니 서둘러 진행 하는 것을 추천드립니다. 13 00:01:27,122 --> 00:01:32,484 그리고 과제 2를 하실때 팁을 드리자면 현재 대다수가 Googld Cloud를 쓰고 계신데 14 00:01:32,484 --> 00:01:38,586 Googld Cloud에서 instances를 사용하지 않을 시에는 반드시 종료시켜 줘야 합니다. 아니면 요금이 계속 지불됩니다. 15 00:01:38,586 --> 00:01:42,899 여러분들이 쿠폰을 너무 많이 씁니다. 16 00:01:42,899 --> 00:01:52,223 instance에서 아무 작업도 하지 않더라도 켜져 있으면 요금이 부과됩니다. 17 00:01:52,223 --> 00:01:57,118 그러니 사용하지 않으면 반드시 종료시켜 줘야 합니다. 18 00:01:57,118 --> 00:02:04,970 여기 제 대쉬보드 화면인데, 이런 식으로 확실하게 STOP 버튼을 눌러줘야 합니다. 19 00:02:04,970 --> 00:02:08,644 매일 매일 이렇게 종료 시켜 주시기 바랍니다. 20 00:02:09,481 --> 00:02:20,853 그리고 Googld Cloud를 사용할 때 아셔하 할 것은 GPU를 쓰는 것이 CPU보다 더 비싸다는 것입니다. 21 00:02:20,853 --> 00:02:28,322 GPU를 쓰시면 어림잡아 시간당 거의 1 달러를 사용하게 됩니다. 상당히 가격이 높습니다. 22 00:02:28,322 --> 00:02:39,739 CPU instances는 조금 더 쌉니다. 추천 드리는 방법은 GPU instance는 GPU가 필요할 때만 쓰는 것입니다. 23 00:02:39,739 --> 00:02:47,377 가령 과제 2를 하실 때 대게는 CPU만 있으면 됩니다. 따라서 CPU instance만 사용하면 됩니다. 24 00:02:47,377 --> 00:02:52,990 하지만 과제2의 마지막 문제를 풀때 사용하는 Tensorflow와 PyTorch는 GPU가 필요합니다. 25 00:02:52,990 --> 00:02:58,897 CPU와 GPU instance를 각각 만들고 정말 필요할 때만 GPU instance를 사용하시길 권장드립니다. 26 00:02:58,897 --> 00:03:04,307 그러니 비용이 얼마나 지불되는 지를 모니터링 하면서 지나치게 지불되는 것을 주의하시기 바랍니다. 27 00:03:04,307 --> 00:03:07,748 공지사항 관련한 질문사항 있나요? 28 00:03:11,180 --> 00:03:12,182 질문있나요? 29 00:03:12,182 --> 00:03:13,902 [학생이 질문] 30 00:03:13,902 --> 00:03:16,133 RAM을 얼마나 사용해야 하냐고 하셨는데 31 00:03:16,133 --> 00:03:21,863 과제용으로는 8~16기가면 충분합니다. 32 00:03:21,863 --> 00:03:27,114 CPU나 RAM을 너무 많이 추가하면 돈이 많이 듭니다. 33 00:03:27,114 --> 00:03:34,542 CPU는 2~4개를 쓰고 RAM은 8~16 기가를 쓰시면 과제 하실 때 충분한 사양입니다. 34 00:03:36,636 --> 00:03:40,417 지난 시간 내용을 복습해 보면 Activation function을 배웠습니다. 35 00:03:40,417 --> 00:03:44,962 지난 시간에 다양한 Activation Function과 각각의 특성을 배웠습니다. 36 00:03:44,962 --> 00:03:59,736 10년 전에는 sigmoid가 아주 유명했습니다. 하지만 Vanishing gradients가 생기는 문제가 있었죠 tanh도 마찬가지 이구요 37 00:03:59,736 --> 00:04:09,230 그래서 요즘은 대부분 ReLU를 씁니다. 일반적인 네트워크에서 가장 잘 동작하는 녀석입니다. 38 00:04:09,230 --> 00:04:16,820 그래서 가중치 초기화에 대해서도 배웠습니다. 39 00:04:16,820 --> 00:04:23,787 가중치가 지나치게 작으면 activatiom이 사라집니다. 40 00:04:23,788 --> 00:04:29,583 작은 값이 여러 번 곱해지기 때문에 점점 0이 되는 것이었습니다. 41 00:04:29,583 --> 00:04:33,072 결국 모든 값이 0이 되고 학습은 일어나지 않습니다. 42 00:04:33,072 --> 00:04:41,208 반면에 가중치가 너무 큰 값으로 초기화되면 그 값이 또 계속 곱해질 것이고 결국은 터져버릴 것입니다(explode). 43 00:04:41,208 --> 00:04:45,389 이 경우에도 학습이 일어나지 않을 것입니다. 44 00:04:45,389 --> 00:04:58,531 Xavier/MSRA(HE) Initialzation 같은 방법으로 초기화를 잘 시켜주면 Activation의 분포를 좋게 유지시킬 수 있습니다. 45 00:04:58,531 --> 00:05:04,328 명심해야 할 점은 위의 것들이 Network가 깊어지면 깊어질 수록 더 중요하다는 것입니다. 46 00:05:04,328 --> 00:05:11,620 Network가 깊어지면 깊어질수록 가중치를 더 많이 곱하게 되기 때문입니다. 47 00:05:11,620 --> 00:05:23,666 그리고 데이터 전처리가 있었죠. CNN은 zero-mean을 주로 사용하며, 그 밖에 zero-mean, unit variance에 대해서도 배웠습니다. 48 00:05:23,666 --> 00:05:29,968 제가 여러분에게 왜 그걸 해야하는 지를 좀 더 직관적으로 말씀 드리겠습니다. 49 00:05:29,968 --> 00:05:39,532 자 여기에서 우리는 Binary classification 문제를 풉니다. 빨간/파란 점들을 나누는 것입니다. 50 00:05:39,532 --> 00:05:46,948 왼쪽의 경우 not normalized/centered 데이터 입니다. 51 00:05:46,948 --> 00:05:55,007 이 경우에도 물론 classification이 가능하지만 선이 조금만 움직여도 classification이 잘 되지 않습니다. 52 00:05:55,007 --> 00:06:05,992 왼쪽의 예시가 의미하는 것은 손실 함수가 아주 약간의 가중치 변화에도 엄청 예민하다는 것입니다. 53 00:06:07,315 --> 00:06:14,554 왼쪽의 경우 동일한 함수를 쓰더라도 학습 시키기 아주 어렵습니다. 재차 말씀드리지만 Loss가 파라미터에 너무 민감하기 때문입니다. 54 00:06:14,554 --> 00:06:25,351 반면 오른쪽은 데이터의 중심을 원점에 맞추고(zero-center), Unit variance로 만들어 준 경우 입니다. 55 00:06:25,351 --> 00:06:35,523 오른쪽에서의 선이 조금씩 흔들리는 경우는 보면 손실 함수는 이런 가중치의 변동에 덜 민감함을 알 수 있습니다. 56 00:06:35,523 --> 00:06:41,064 이 경우가 최적화가 더 쉽습니다. 학습이 더 잘되는 것입니다. 57 00:06:41,064 --> 00:06:46,539 그리고 이는 Linear classification의 경우에만 국한되는 것이 아닙니다. 58 00:06:46,539 --> 00:06:57,756 Neural network 내부에도 다수의(interleavings) linear classifer가 있다고 생각할 수 있습니다. 59 00:06:59,078 --> 00:07:05,687 이 경우에도 Neural network의 입력이 zero-centered가 아니고 Unit variance가 아닌 경우라면 60 00:07:05,687 --> 00:07:15,632 레이어의 Weight matrix가 아주 조금만 변해도 출력은 엄청 심하게 변하게 됩니다. 이는 학습을 어렵게 합니다. 61 00:07:15,632 --> 00:07:20,481 이를 통해 왜 nomalization가 중요한지를 좀 더 직관적으로 이해하실 수 있을 것입니다. 62 00:07:21,864 --> 00:07:26,862 자 우리는 Normalization이 엄청 중요하다는 것을 알고 있기 때문에 batch normalization도 배웠습니다. 63 00:07:26,862 --> 00:07:36,030 이는 actications이 zero mean과 unit variance가 될 수 있도록 레이어를 하나 추가하는 방법이었습니다. 64 00:07:36,030 --> 00:07:41,465 제가 이 슬라이드에 batch normalization 수식을 다시한번 적어 봤습니다. 65 00:07:41,465 --> 00:07:45,172 이 슬라이드를 보면 과제 2를 하실 때 수월할 것입니다. 66 00:07:45,172 --> 00:07:59,254 BN에서는 forward pass 시에 미니배치에서의 평균과 표준편차를 계산해서 Normalization을 수행했습니다. 67 00:07:59,254 --> 00:08:05,641 그리고 레이어의 유연한 표현성(expressivity)을 위해서 scale, shift 파라미터를 추가했습니다. 68 00:08:05,641 --> 00:08:09,990 과제 2를 하실때 이를 참고하시기 바랍니다. 69 00:08:09,990 --> 00:08:18,146 그리고 학습 과정을 다루는 방법도 배웠습니다. 학습 도중 Loss curve가 어떻게 보여야 하는지도 말이죠 70 00:08:18,146 --> 00:08:26,683 여기 예제 네트워크가 있습니다. 주말동안 한번 돌려봤습니다. 저는 학습을 진행할 때 이런 식으로 진행합니다. 71 00:08:26,683 --> 00:08:35,795 가운데 그래프는 시간에 따른 Loss 값을 나타냅니다. 네트워크가 Loss를 줄이고 있으면 잘 하고 있는 것이죠 72 00:08:35,795 --> 00:08:48,464 맨 오른쪽 그래프를 보면 X는 시간축이고 Y는 성능 지표입니다. Training/Validation set의 성능지표를 나타냅니다. 73 00:08:48,465 --> 00:08:58,680 이를 해석해보면 Training set의 성능을 계속 올라가죠 Loss도 계속 내려갑니다. 하지만 validation은 침체하고 있습니다. 74 00:08:58,680 --> 00:09:05,066 이런 경우는 overfititing이라고 할 수 있겠습니다. 추가적인 regularization이 필요한 것입니다. 75 00:09:06,317 --> 00:09:09,504 그리고 이전 강의에서 hyperparameter search도 배웠습니다. 76 00:09:09,504 --> 00:09:14,798 네트워크에는 무수히 많은 하이퍼파라미터가 존재합니다. 이를 올바르게 잘 선택하는 것은 상당히 중요합니다. 77 00:09:14,798 --> 00:09:20,725 그리고 grid search와 random search를 배웠습니다. 이론상 random search가 더 좋았습니다. 78 00:09:20,725 --> 00:09:30,669 왜냐하면 성능이 특정 하이퍼파라미터에 의해 크게 좌우될 때 그 파라미터를 좀 더 넓은 범위로 탐색할 수 있기 때문입니다. 79 00:09:30,669 --> 00:09:37,005 그리고 하이퍼파라미터 최적화 시에 coarse search 이후 fine search를 한다고 배웠습니다. 80 00:09:37,005 --> 00:09:43,408 처음에는 하이퍼파라미터를 조금 더 넒은 범위에서 찾습니다. Interation도 작게 줘서 학습시켜봅니다.(coarse) 81 00:09:43,408 --> 00:09:47,973 그리고 결과가 좋은 범위로 좁히는 것입니다. 82 00:09:47,973 --> 00:09:51,666 그리고 iterations를 조금 더 돌면서 더 작은 범위를 다시 탐색합니다. (fine search) 83 00:09:51,666 --> 00:09:56,708 적절한 하이퍼파라미터를 찾을 때 까지 이 과정을 반복합니다. 84 00:09:56,708 --> 00:10:04,455 가장 중요한 점은 coarse range를 설정할 때 가능한 최대한 넓은 범위를 설정해 줘야 한다는 것입니다. 85 00:10:04,455 --> 00:10:13,746 그 범위가 하이퍼파라미터 범위의 끝에서 끝까지 다 살펴볼 수 있도록 할수록 좋습니다. 충분히 넓은 범위를 사용해야 합니다. 86 00:10:17,462 --> 00:10:18,295 질문 있나요? 87 00:10:20,044 --> 00:10:26,672 [학생이 질문] 88 00:10:31,840 --> 00:10:34,554 질문은 보통 하이퍼파라미터를 몇 개씩 선택하는지 입니다. 89 00:10:34,554 --> 00:10:38,244 여기 예제에서는 2개 인데 보통은 2개보단 많습니다. 90 00:10:38,244 --> 00:10:45,442 그 선택은 모델에 따라 다릅니다. 선택한 하이퍼파라미터의 수가 많을 수록 기하급수적으로 경우의 수가 늘어납니다. 91 00:10:45,442 --> 00:10:48,012 때문에 한번에 너무 많이 할 수 는 없습니다. 92 00:10:48,012 --> 00:10:51,737 또 이는 여러분이 얼마나 많은 자원을 학습에 사용할 수 있는지도 중요합니다. 93 00:10:51,737 --> 00:10:55,745 이는 사람마다 다르고 실험마다 다릅니다. 94 00:10:55,745 --> 00:11:05,353 저같은 경우 두 세가지 정도를 고르는 편이고 많아도 네 가지 정도만 선택합니다. 그 이상이면 out of control이 되버립니다. 95 00:11:05,353 --> 00:11:10,406 일반적으로는 Learning rate가 가장 중요합니다. Learning rate를 가장 먼저 선택해 놔야만 합니다. 96 00:11:10,406 --> 00:11:19,542 regularization, learning rate decay, model size 같은 것들은 LR보단 덜 중요합니다. 97 00:11:19,542 --> 00:11:22,723 Block Coordinate Descent(BCD) 같은 방법을 쓸 수도 있습니다. 98 00:11:22,723 --> 00:11:27,459 가령, 우선 Learning rate를 정해놓은 다음에 다양한 모델 사이즈를 시도해 보는 것입니다. 99 00:11:27,459 --> 00:11:30,759 이 방법을 쓰면 기하급수적으로 늘어나는 Search space를 조금은 줄일 수 있습니다. 100 00:11:30,759 --> 00:11:35,370 하지만 이 방법은 정확히 어떤 순서로 어떻게 찾아야 할지 정해야 하는 것이 가장 큰 문제입니다. 101 00:11:36,253 --> 00:11:38,120 다른 질문 있으신가요? 102 00:11:38,120 --> 00:11:57,041 [학생이 질문] 103 00:11:57,041 --> 00:12:04,537 질문은 우리가 어떤 하이퍼파리미터 값을 변경할 시에 다른 하이퍼파라미터 의 최적 값이 변해버리는 경우가 빈번하냐는 것입니다. 104 00:12:04,537 --> 00:12:11,339 그런 일이 가끔 발생하긴 합니다. Learning rates가 이런 문제에 덜 민감함에도 실제로 이런 일이 발생하곤 합니다. 105 00:12:11,339 --> 00:12:18,130 Leraning rates가 좋은 범위 내에 속했으면 하지만 보통은 optimal 보다는 작은 값이고 학습 속도가 길어지곤 합니다. 106 00:12:18,130 --> 00:12:31,291 이런 경우에는, 오늘 배우게 될, 더 좋은(fancier) 최적화 방법을 사용하면 모델이 learning rate에 덜 민감하도록 할 수 있습니다. 107 00:12:31,291 --> 00:12:32,962 다른 질문 있으신가요? 108 00:12:32,962 --> 00:12:37,308 [학생이 질문] 109 00:12:37,308 --> 00:12:41,292 질문은 Learning rate를 작게 하고 Epoch을 늘리면 어떤 일이 발생하는지 입니다. 110 00:12:41,292 --> 00:12:45,139 그렇게 되면 엄청 오래 걸리겠죠 111 00:12:45,139 --> 00:12:48,383 [학생이 질문] 112 00:12:48,383 --> 00:12:54,853 Learning rates를 낮추고 오랫동안 학습시키게 되면 이론적으로는 항상 동작하는 것이 맞습니다. 113 00:12:54,853 --> 00:13:00,491 하지만 실제로는 Learning rate가 0.01이냐 0.001이냐는 상당히 중요한 문제가 됩니다. 114 00:13:00,491 --> 00:13:03,931 여러분이 적절한 Leraning rate를 찾으면 6시간, 12시간 또는 하루면 학습을 다 시킬 수 있을 텐데 115 00:13:03,931 --> 00:13:11,911 그런데 여러분이 엄청 조심스러워서 Learning rate를 10배, 100배 줄여 버라면 하루면 끝나는 것이 100일이 걸릴수 있습니다. 116 00:13:11,911 --> 00:13:16,400 그럼 세 달이 걸리게 되는 것입니다. 좋지 않은 경우입니다. 117 00:13:16,400 --> 00:13:20,668 보통 컴퓨터과학 분야를 배울때 이런 constants(10배 100배)를 중요하게 다루지 않는 경향이 있는데 118 00:13:20,668 --> 00:13:25,444 당신은 실제로 훈련하는 것에 대해 생각하고 있습니다. 그 constants은 많은 문제가됩니다. 119 00:13:25,444 --> 00:13:26,861 다른 질문 있나요? 120 00:13:27,877 --> 00:13:33,385 [학생이 질문] 121 00:13:33,385 --> 00:13:37,807 질문은 Low learning rate를 주게되면 local optima에 빠질 수 있지 않냐는 것입니다. 122 00:13:37,807 --> 00:13:42,601 이는 직관적으로는 그럴 수 있겠지만 실제로 그런 일은 많이 발생하지는 않습니다. 123 00:13:42,601 --> 00:13:47,030 이에 관한 내용을 오늘 잠시 뒤에 다시 배울 것입니다. 124 00:13:47,030 --> 00:13:53,151 오늘은 Neural networks를 학습시킬 때 필요한 흥미롭고 아주 중요한 문제를 몇 가지 배워보도록 하겠습니다. 125 00:13:53,151 --> 00:13:59,655 제가 이전에 더 강력한 최적화 알고리즘이 있다고 앞서 몇 번 언급한 적이 있었습니다. 126 00:13:59,655 --> 00:14:07,067 오늘은 사람들이 많이 사용하는 그 강력한 알고리즘들에 대해서 좀 더 자세히 알아보는 시간이 되겠습니다. 127 00:14:07,067 --> 00:14:10,364 지난 강의에 Regularization에 대해서도 조금 배웠었죠 128 00:14:10,364 --> 00:14:15,806 네트워크의 Train/Test Error 간의 격차를 줄이고자 사용하는 추가적인 기법입니다. 129 00:14:15,806 --> 00:14:22,143 Neural Network에서 실제로 사람들이 사용하고 있는 Regularization 전략에 대해서 다뤄보도록 하겠습니다. 130 00:14:22,143 --> 00:14:26,401 그리고 Transfer learning에 대해서도 배울 것입니다. 131 00:14:26,401 --> 00:14:31,490 원하는 양 보다 더 적은 데이터만을 가지고 있을때 사용할 수 있는 방법입니다. 132 00:14:32,821 --> 00:14:39,885 지난 강의를 돌이켜보면 Neural network에서 가장 중요한 것은 바로 최적화 문제 였다는 것을 알 수 있습니다. 133 00:14:39,885 --> 00:14:50,982 Nerwork의 가중치에 대해서 손실 함수를 정의해 놓으면 이 손심 함수는 그 가중치가 얼마나 좋은지 나쁜지를 알려줍니다. 134 00:14:50,982 --> 00:14:56,508 그리고 우리는 손심 함수가 가중치에 대한 "산(landscape)"이라고 상상해 볼 수 있을 것입니다. 135 00:14:56,508 --> 00:15:04,142 여기 맨 오른쪽 사진에 간단한 예제를 가져왔습니다. X/Y축은 두 개의 가중치를 의미합니다. 136 00:15:04,142 --> 00:15:07,984 그리고 각 색은 Loss의 값을 나타냅니다. 137 00:15:07,984 --> 00:15:15,195 이 오른쪽의 2차원의 문제를 두 개의 가중치 W_1과 W_2를 최적화 시키는 문제라고 생각해 봅시다. 138 00:15:15,195 --> 00:15:23,203 우리의 목적은 가장 붉은색인 지점을 찾는 것입니다. 즉 가장 낮은 Loss를 가진 가중치를 찾는 것이죠. 139 00:15:23,203 --> 00:15:29,099 자 지금까지 배운 것을 생각해 봅시다. 가장 간단한 최적화 알고리즘은 바로 Stochastic Gradient Descent 입니다. 140 00:15:29,099 --> 00:15:32,393 이 세 줄로 된 엄청 간단한 알고리즘이죠 141 00:15:32,393 --> 00:15:39,179 우선 미니 배치 안의 데이터에서 Loss를 계산합니다. 142 00:15:39,179 --> 00:15:44,656 그리고 'Gradient 의 반대 방향" 을 이용해서 파라미터 벡터를 업데이트합니다. 143 00:15:44,656 --> 00:15:48,798 반대 방향인 이유는 손실 함수를 내려가는 방향 이어야 하기 때문입니다. 144 00:15:48,798 --> 00:15:56,282 이 단계를 계속 반복하면 결국 붉은색 지역으로 수렴할 것이고 Loss가 낮을 것입니다. 145 00:15:56,282 --> 00:16:05,462 하지만 이 심플한 알고리즘을 실제로 사용하게 되면 몇 가지 문제에 봉착하고 맙니다. 146 00:16:05,462 --> 00:16:08,713 SGD의 문제점 중 하나는, 147 00:16:08,713 --> 00:16:18,969 가령 우리의 손실함수가 이런 식으로 생겼다고 생각해 봅시다. 여기에 똑같이 W_1과 W_2가 있다고 해봅시다. 148 00:16:18,969 --> 00:16:23,472 둘중 어떤 하나는 업데이트를 해도 손실 함수가 아주 느리게 변합니다. 149 00:16:23,472 --> 00:16:26,687 즉, 수평 축의 가중치는 변해도 Loss가 아주 천천히 줄어듭니다. 150 00:16:28,152 --> 00:16:34,930 다시 말해 Loss는 수직 방향의 가중치 변화에 훨씬 더 민감하게 반응하는 것입니다. 151 00:16:34,930 --> 00:16:40,757 다시 말해 현재 지점에서 Loss는 bad condition number를 지니고 있다고 말할 수 있을 것입니다. 152 00:16:40,757 --> 00:16:46,050 이 지점의 Hessian maxrix의 최대/최소 singular values 값의 비율이 매우 안좋다는 뜻입니다. 153 00:16:46,050 --> 00:16:50,497 이를 좀 더 직관적으로 이해해보면 우선 Loss가 taco shell 같은 모양입니다. 154 00:16:50,497 --> 00:16:54,393 한 방향으로는 엄청나게 민감한 반면에 다른 방향으로는 덜 민감한 상태에 있는 것입니다. 155 00:16:54,393 --> 00:17:00,633 그렇다면 질문입니다. 이런 상황에서 SGD으로 학습이 되는 과정은 어떤 모습일까요? 156 00:17:05,310 --> 00:17:12,196 손실 함수가 이런 식으로 생긴 환경에서 SGD를 수행하면, 이런 특이한 지그재그 형태를 볼 수 있을 것입니다. 157 00:17:12,197 --> 00:17:22,111 왜냐하면 이런 함수에서는 gradient의 방향이 고르지 못하기 때문입니다. 158 00:17:22,112 --> 00:17:29,335 Gradient를 계산하고 업데이트 하게 되면 line을 넘나들면서 왔다갔다 하게 됩니다. 159 00:17:29,335 --> 00:17:35,995 Loss에 영향을 덜 주는 수평방향 차원의 가중치는 업데이트가 아주 느리게 진행됩니다. 160 00:17:35,995 --> 00:17:41,551 이렇게 빠르게 변하는 수직 차원을 가로지르면서 지그지그로 아주 지저분하게(nasty) 움직이게 됩니다. 161 00:17:41,551 --> 00:17:50,139 아주 바람직하지 않은 행동입니다. 그리고 이 문제는 고차원 공간에서 훨씬 더 빈번하게 발생합니다. 162 00:17:51,186 --> 00:18:00,617 우리가 본 예시 그림은 2차원 밖에 되지 않습니다만 실제로는 가중치가 수천 수억개 일 수 있을 것입니다. 163 00:18:00,617 --> 00:18:14,221 이 경우 수억개의 방향으로 움직일 수 있습니다. 이런 수억개의 방향중에 불균형한 방향이 존재한다면 SGD는 잘 동작하지 않을 것입니다. 164 00:18:14,221 --> 00:18:20,573 수억개의 파라미터가 있다고 했을때 이런 불균형의 발생 비율은 상당히 높습니다. 165 00:18:20,573 --> 00:18:26,398 고차원 공간에서 발생할 수 있는 이런 문제는 실제로도 정말 큰 문제가 됩니다. 166 00:18:27,793 --> 00:18:33,564 SGD에서 발생하는 또 다른 문제는 local minima 와 saddle points와 관련된 문제입니다. 167 00:18:33,564 --> 00:18:44,003 그림을 좀 바꿨습니다. 이제는 X축은 어떤 하나의 가중치를 나타내고 Y축은 Loss를 나타내고 있습니다. 168 00:18:44,003 --> 00:18:51,583 우선 위의 그래프를 보면, 이 휘어진 손실함수는 중간에 "valley"가 하나 있습니다. 169 00:18:51,583 --> 00:18:55,036 이런 상황에서 SGD는 어떻게 움직일까요? 170 00:18:55,036 --> 00:18:57,031 [학생이 대답] 171 00:18:57,031 --> 00:19:04,454 이 경우 SGD는 멈춰버립니다. 왜냐하면 gradient가 0이 되기 때문이죠. locally falt 합니다. 172 00:19:04,454 --> 00:19:09,194 SGD의 동작을 생각해보면 gradient를 계산하고 그 반대방향으로 이동하는 것 이었습니다. 173 00:19:09,194 --> 00:19:15,862 저 위치에서는 "opposite gradient" 도 0 이 되며, 따라서 학습이 멈춰버리게 됩니다. 174 00:19:15,862 --> 00:19:19,406 또 다른 문제는 saddle points에 관한 것입니다. 175 00:19:19,406 --> 00:19:26,140 local minima는 아니지만, 한쪽 방향으로는 증가하고 있고 다른 한쪽 방향으로는 감소하고 있는 지역을 생각해 볼 수 있습니다. 176 00:19:26,140 --> 00:19:28,953 이런 곳에서도 gradient는 0이 됩니다.(아래 그림) 177 00:19:28,953 --> 00:19:35,899 saddle point에서도 gradient = 0 이므로 멈추게 됩니다. 178 00:19:35,899 --> 00:19:48,122 비록 이처럼 1차원의 예제만 봐서는 local minima가 엄청 심각하고 saddle point는 좀 덜 심각해 보이지만, 179 00:19:48,122 --> 00:19:57,171 고차원 공간에서는 그 반대입니다. 여러분에게 1억 차원의 공간이 있다고 생각해 봅시다. 여기에서 saddle point는 무엇일까요? 180 00:19:57,171 --> 00:20:03,135 Saddle point가 의미하는 것이 어떤 방향은 Loss가 증가하고 몇몇 방향은 Loss가 감소하고 있는 곳을 생각해 볼 수 있습니다. 181 00:20:03,135 --> 00:20:09,591 1억개의 차원에서 생각해보면 이는 정말 빈번하게 발생합니다. 사실 거의 모든 곳에서 발생한다고 할 수 있습니다. 182 00:20:09,591 --> 00:20:16,744 Local minima를 생각해보면 1억 개의 방향을 계산했는데 그 방향이 전부 Loss가 상승하는 방향이라는 것입니다. 183 00:20:16,744 --> 00:20:22,316 고차원 공간을 생각하면 그런 일이 발생하는 것은 매우 드문 경우입니다. 184 00:20:23,270 --> 00:20:33,283 지난 몇 년간 알려진 사실은 very large neural network가 local minima 보다는 saddle point에 취약하다는 것입니다. 185 00:20:33,283 --> 00:20:40,140 그리고 또한 saddle point 뿐만 아니라 saddle point의 근처에서도 문제는 발생합니다. 186 00:20:40,140 --> 00:20:47,935 아래 예시를 보면 saddle point 근처에서 gradient가 0 은 아니지만 기울기가 아주 작습니다. 187 00:20:47,935 --> 00:20:53,611 그것이 의미하는 바는 gradient를 계산해서 업데이트를 해도 기울기가 아주 작기 때문에 188 00:20:53,611 --> 00:21:01,872 현재 가중치의 위치가 saddle point 근처라면 업데이트는 아주 느리게 진행됩니다. 189 00:21:01,872 --> 00:21:10,115 이는 아주 큰 문제입니다. 그리고 SGD의 또 다른 문제가 있습니다. 190 00:21:10,115 --> 00:21:13,521 SGD는 Stochastic gradient descent라는 것을 다시한번 명심하시기 바랍니다. 191 00:21:13,521 --> 00:21:20,586 사실 손실함수를 계산할 때는 엄청 엄청 많은 Traing set 각각의 loss를 전부 계산해야 합니다. 192 00:21:20,586 --> 00:21:26,119 이 예시의 N이 전체 training set일 경우에 이 값은 "n = 백만"이 될 수도 있습니다. 193 00:21:26,119 --> 00:21:29,347 Loss를 계산할 때 마다 매번 전부를 계산하는 것은 어렵습니다. 194 00:21:29,347 --> 00:21:36,957 그래서 실제로는 미니배치의 데이터들만 가지고 실제 Loss를 추정하기만 합니다. 195 00:21:36,957 --> 00:21:42,148 이는 매번 정확한 gradient를 얻을 수가 없다는 것을 의미합니다. 196 00:21:42,148 --> 00:21:46,773 대신에 gradient의 부정확한 추정값(noisy estimate) 만을 구할 뿐입니다. 197 00:21:46,773 --> 00:21:50,575 오른쪽에 보이는 것은 제가 좀 과장해서 그린 것입니다. 198 00:21:50,575 --> 00:21:59,927 각 지점의 gradient에 random uniform noise를 추가하고 SGD를 수행하게 만들었습니다. 199 00:21:59,927 --> 00:22:07,987 따라서 실제로 SGD가 이런식으로 동작하진 않지만 이 예제로 gradient에 noise가 들어가면 어떻게 되는지 알 수 있습니다. 200 00:22:07,987 --> 00:22:14,036 손실함수 공간을 이런식으로 비틀거리면서 돌아다니게 되면 minima까지 도달하는데 시간이 더 오래 걸릴 것입니다. 201 00:22:15,723 --> 00:22:18,966 지금까지 SGD에 어떤 문제가 있는지에 대해서 이야기해 보았습니다. 202 00:22:18,966 --> 00:22:20,956 질문 있나요? 203 00:22:20,956 --> 00:22:25,123 [학생이 질문] 204 00:22:29,099 --> 00:22:34,435 질문은 바로 SGD를 쓰지 않고 그냥 GD를 쓰면 이런 문제가 전부 해결되는지 입니다. 205 00:22:35,281 --> 00:22:44,106 자 이전의 taco shell에서의 문제를 다시한번 살펴보면 full batch gradient descent에서도 같은 문제가 발생합니다 206 00:22:44,106 --> 00:22:54,120 Noise의 문제도 한번 볼까요. Noise는 미니배치이기 때문에서만이 아니라 네트워크의 explicit stochasticity 로도 발생합니다. 207 00:22:54,120 --> 00:22:57,736 이는 나중에 더 살펴 볼 것이지만 이는 여전히 문제가 됩니다. 208 00:22:57,736 --> 00:23:05,101 Saddle points 또한 full batch GD에서 문제가 됩니다. 전체 데이터를 사용한다고 해도 여전히 나타날 수 있겠죠 209 00:23:05,101 --> 00:23:10,249 기본적으로 full batch gradient descent를 사용한다 하더라도 이런 문제들이 해결되지는 않습니다. 210 00:23:10,249 --> 00:23:16,604 이러한 위험요소들을 다루기 위해서는 더 좋은 최적화 알고리즘이 필요합니다. 211 00:23:16,604 --> 00:23:21,966 이번 문제들의 대다수를 해결할 수 있는 아주 간단한 방법이 하나 있습니다. 212 00:23:21,966 --> 00:23:26,978 SGD에 momentum term을 추가하는 것이죠 213 00:23:26,978 --> 00:23:32,923 왼쪽은 classic 버전의 SGD입니다. 오로지 gradient 방향으로만 움직이는 녀석이죠 214 00:23:32,923 --> 00:23:43,062 반면 오른쪽은 SGD + momentum 입니다. 엄청 조금의 변화만 있습니다. 2개의 수식과 5라인의 코드를 보실 수 있죠 215 00:23:43,062 --> 00:23:51,331 아이디어는 아주 간단합니다. 그저 velocity를 유지하는 것입니다. gradient 를 계산할 때 velocity를 이용합니다. 216 00:23:51,331 --> 00:23:57,811 현재 미니배치의 gradient 방향만 고려하는 것이 아니라 velocity를 같이 고려하는 것입니다. 217 00:23:57,811 --> 00:24:04,825 여기에는 하이퍼 파라미터 rho가 추가되었습니다. momemtum의 비율을 나타냅니다. 218 00:24:05,925 --> 00:24:16,848 velocity의 영향력을 rho의 비율로 맞춰주는데 보통 0.9와 같은 높은 값으로 맞춰줍니다. 219 00:24:16,848 --> 00:24:21,173 velocity에 일정 비율 rho를 곱해주고 현재 gradient를 더합니다. 220 00:24:21,173 --> 00:24:26,999 이를 통해서 우리는 이제 gradient vector 그대로의 방향이 아닌 velocity vector의 방향으로 나아가게 됩니다. 221 00:24:28,327 --> 00:24:34,548 엄청 간단한 방법이지만 지금까지 말했던 문제들을 해결하는데 많은 도움을 줄 수 있습니다. 222 00:24:34,548 --> 00:24:44,809 local minima와 saddle points문제를 생각해보면 물리적으로 공이 굴러내려오는 것을 상상해 볼 수 있습니다. 223 00:24:44,809 --> 00:24:48,215 이 공은 떨어지면 속도가 점점 빨라집니다. 224 00:24:48,215 --> 00:24:56,922 이 공은 local minima에 도달해도 여전히 velocity를 가지고 있기 때문에 gradient = 0 이라도 움직일 수 있습니다. 225 00:24:56,922 --> 00:25:01,039 때문에 local minima를 극복할 수 있게 되고 계속해서 내려갈 수 있습니다. 226 00:25:01,039 --> 00:25:03,809 saddle points에서도 비슷한 일이 일어나겠죠 227 00:25:03,809 --> 00:25:10,734 saddle point 주변의 gradient가 작더라도, 굴러내려오는 속도가 있기 때문에 velocity를 가지게 됩니다. 228 00:25:10,734 --> 00:25:16,462 때문에 saddle point를 잘 극복해 내고 계속 밑으로 내려올 수 있는 것입니다. 229 00:25:16,462 --> 00:25:21,949 업데이트가 잘 안되는 경우(poor conditioning) 를 다시 한번 살펴보겠습니다. 230 00:25:21,949 --> 00:25:31,105 아래와 같이 지그재그로 움직이는 상황이라면 momentum이 이 변동을 서로 상쇄시켜 버립니다. 231 00:25:31,105 --> 00:25:46,006 이를 통해서 loss에 만감한 수직 방향의 변동은 줄여주고 수평방향의 움직임은 점차 가속화 될 것입니다. 232 00:25:46,006 --> 00:25:51,344 momentum을 추가하게 되면 high condition number problem을 해결하는 데 도움이 되는 것입니다. 233 00:25:51,344 --> 00:26:05,207 오른쪽을 보면 검은색이 일반 SGD입니다. 지그지그로 움직이죠. 파란색이 Momentum SGD입니다. 234 00:26:05,207 --> 00:26:12,644 Momentum을 추가해서 velocity가 생기면 결국 noise가 평균화되버립니다. 235 00:26:12,644 --> 00:26:20,337 보통의 SGD가 구불구불 움직이는 것에 비해서 momemum은 minima를 향해서 더 부드럽게 움직입니다. 236 00:26:20,337 --> 00:26:21,532 질문 있나요? 237 00:26:21,532 --> 00:26:25,699 [학생이 질문] 238 00:26:34,776 --> 00:26:40,465 문제는 어떻게 SGD Momemtum이 poorly conditioned coordinate 문제를 해결할 수 있는지 입니다. 239 00:26:40,465 --> 00:26:49,125 우선 velocity estimation term에서 velocity가 어떻게 계산되는지를 보면 gradient를 계속해서 더해갑니다. 240 00:26:49,125 --> 00:26:56,603 이는 하이퍼파라미터인 rho에 영향을 받습니다. 그리고 현재 gradient가 상대적으로 작은 값이고 241 00:26:56,603 --> 00:26:59,254 그리고 이 상황에서 rho가 적절한 값으로 잘 동작한다고 하면 242 00:26:59,254 --> 00:27:05,512 그러면 velocity가 실제 gradient보다 더 커지는 지점 까지 조금씩 증가할 것입니다. 243 00:27:05,512 --> 00:27:10,377 이는 poorly conditioned dimension에서 더 빨리 학습될 수 있도록 도와줍니다. 244 00:27:12,569 --> 00:27:18,020 SGD momentum를 연상할 때 유용한 그림이 있습니다. 245 00:27:18,020 --> 00:27:20,273 빨간 점이 현재 지점입니다. 246 00:27:20,273 --> 00:27:30,075 Red Vector는 현재 지점에서의 gradient의 방향을 나타냅니다. Green vector는 Velocity vector입니다. 247 00:27:30,075 --> 00:27:36,317 실제 업데이트는(autual step) 이 둘의 가중평균으로 구할 수 있습니다. 248 00:27:36,317 --> 00:27:40,049 이는 gradient의 noise를 극복할 수 있게 해줍니다. 249 00:27:40,049 --> 00:27:47,724 Momentum의 변형이 있습니다. Nesterov accelerated gradient 인데, Nesterov momentum 라고도 합니다. 250 00:27:47,724 --> 00:27:51,737 계산하는 순서를 조금 바꾼 것입니다. 251 00:27:51,737 --> 00:28:00,285 기본 SGD momentum은 "현재 지점" 에서의 gradient를 계산한 뒤에 velocity와 섞어 줍니다. 252 00:28:00,285 --> 00:28:04,229 Nesterov를 사용하면 방법이 조금 다릅니다. 253 00:28:04,229 --> 00:28:10,765 빨간 점에서 시작해서 우선은 Velocity방향으로 움직입니다. 254 00:28:10,765 --> 00:28:18,732 그리고 그 지점에서의 gradient를 계산합니다. 그리고 다시 원점으로 돌아가서 둘을 합치는 것입니다. 255 00:28:18,732 --> 00:28:25,679 완벽한 설명은 아니지만 두 정보를 약간 더 섞어준다고 생각해 볼 수 있을 것입니다. 256 00:28:25,679 --> 00:28:34,702 velocity의 방향이 잘못되었을 경우에 현재 gradient의 방향을 좀 더 활용할 수 있도록 해줍니다. 257 00:28:34,702 --> 00:28:39,351 Nesterov는 Convex optimization 문제에서는 뛰어난 성능을 보이지만 258 00:28:39,351 --> 00:28:45,946 하지만 Neural network와 같은 non-convex problem 에서는 성능이 보장되지는 않습니다. 259 00:28:45,946 --> 00:28:51,061 Nesterov의 수식은 다음과 같습니다. 260 00:28:51,061 --> 00:28:57,155 velocity를 업데이트하기 위해서 이전의 velocity와 (x + pv)에서의 gradient를 계산합니다. 261 00:28:57,155 --> 00:29:06,222 그리고 step update는 앞서 계산한 velocity를 이용해서 구해줍니다. 262 00:29:06,222 --> 00:29:07,055 질문 있나요? 263 00:29:08,437 --> 00:29:12,357 [학생이 질문] 264 00:29:12,357 --> 00:29:14,743 질문은 velocity의 초기값을 구하는 좋은 방법이 있는지 입니다. 265 00:29:14,743 --> 00:29:16,998 velocity의 초기값은 항상 0입니다. 266 00:29:16,998 --> 00:29:20,096 이는 하이퍼파라미터가 아닙니다. 그저 0으로 둡니다. 267 00:29:20,096 --> 00:29:21,315 다른 질문 있나요? 268 00:29:21,315 --> 00:29:25,482 [학생이 질문] 269 00:29:31,992 --> 00:29:38,068 직관적으로 보면 velocity은 이전 gradients의 weighted sum입니다. 270 00:29:38,068 --> 00:29:41,466 [학생이 질문] 271 00:29:41,466 --> 00:29:44,027 그리고 더 최근의 gradients에 가중치가 더 크게 부여됩니다. 272 00:29:44,027 --> 00:29:49,716 매 스텝마다 이전 velocity에 rho(0.9 or 0.99) 를 곱하고 현재 gradient를 더해줍니다. 273 00:29:49,716 --> 00:29:54,662 그리고 이를 moving average라고 볼 수 있습니다. (exponentially weighted moving average) 274 00:29:54,662 --> 00:30:00,109 그리고 시간이 지날수록 이전의 gradient들은 exponentially하게 감소합니다. 275 00:30:02,627 --> 00:30:11,632 Nesterov의 공식을 보시게 되면 다소 까다롭게 생겼습니다. 기존에는 Loss와 Gradient를 같은 점(x_t)에서 구했었습니다. 276 00:30:11,632 --> 00:30:19,283 Nesterov는 이 규칙을 조금 비틀어 버렸습니다. 이는 상당히 성가시지만 다행이도 쉽게 해결할 수 있는 변형 공식이 있습니다. 277 00:30:19,283 --> 00:30:29,392 변수들을 적절히 잘 바꿔주면 Nesterov를 조금 다르게 표현할 수 있으며 Loss와 Gradient를 같은 점에서 계산할 수 있게 됩니다. 278 00:30:29,392 --> 00:30:34,093 그리고 수정된 수식을 통해서 우리는 Nesterov를 새롭게 이해해 볼 수 있습니다. 279 00:30:34,093 --> 00:30:41,739 첫 번째 수식은 기존의 momentum과 동일합니다. 280 00:30:41,739 --> 00:30:48,178 기존과 동일하게 velocity 와 계산한 gradient를 일정 비율로 섞어주는 역할을 합니다. 281 00:30:48,178 --> 00:30:51,951 그리고 두 번째로 맨 밑의 수식을 보시기 바랍니다. 282 00:30:51,951 --> 00:30:57,592 우선 현재 점과 velocity를 더해줍니다. 여기 까지는 기존과 동일하죠 283 00:30:57,592 --> 00:31:01,454 그리고 여기에 "현재 velocity - 이전 velocity" 를 계산해서 일정 비율(rho)을 곱하고 더해줍니다. 284 00:31:01,454 --> 00:31:11,271 Nesterov momentum는 현재/이전의 velocity간의 에러보정(error-correcting term)이 추가됐습니다. 285 00:31:13,029 --> 00:31:25,249 SGD, Momentum, Nesterov의 예시를 한번 살펴봅시다. 기본 SGD은 검정색인데 세월아 네월아 내려가고 있습니다. 286 00:31:26,346 --> 00:31:29,598 파란색과 초록색이 momentum과 Nesterov입니다. 287 00:31:29,598 --> 00:31:36,803 momentum방법들은 minima를 그냥 지나쳐 버리는 경향이 있습니다. 이전의 velocity의 영향을 받기 때문입니다. 288 00:31:36,803 --> 00:31:39,849 하지만 스스로 경로를 수정하고는 결국 minima에 수렴합니다. 289 00:31:39,849 --> 00:31:40,682 질문 있나요? 290 00:31:42,023 --> 00:31:46,190 [학생이 질문] 291 00:31:52,024 --> 00:31:58,050 질문은 이 예시만 보면 momentum이 엄청 좋아 보이는데 만일 minima가 엄청 좁고 깊은 곳이라면 어떻게 되는지 입니다. 292 00:31:58,050 --> 00:32:01,527 momentum의 velocity가 오히려 minima를 건너 뛰는 현상도 발생할 수 있지 않을까요? 293 00:32:01,527 --> 00:32:05,232 그 부분은 상당히 흥미롭습니다. 그리고 이에 관련한 최근의 연구들이 주목하는 주제이기도 합니다. 294 00:32:05,232 --> 00:32:09,071 하지만 사실은 그렇게 좁고 깊은(sharp) minima는 좋은 minima가 아닙니다. 295 00:32:09,071 --> 00:32:17,601 그리고 사실 우리는 그런 곳에 도달하는 것도 원하지 않습니다. 좁고 깊은 minima는 훨씬 더 심한 overfits을 불러오게 됩니다. 296 00:32:17,601 --> 00:32:22,026 가령 Training set을 두배 늘어났다고 생각해보면, 최적화 시키는 산의 지형(landscape)자체가 바뀌게 될 것입니다. 297 00:32:22,026 --> 00:32:27,420 Training data이 더 많이 모이면 그런 민감한 minima는 점점 사라집니다. 298 00:32:27,420 --> 00:32:31,189 여기에서 얻을 수 있는 직관은 우리가 원하는 minima는 아주 평평한 minima 라는 것입니다. 299 00:32:31,189 --> 00:32:35,933 왜냐하면 "아주 평평한 minima"는 Training data의 변화에 좀 더 강인할 지도 모르기 때문입니다. 300 00:32:35,933 --> 00:32:40,453 결국 평평한 minima가 더 일반화를 잘 할 수도 있으며, Testing data에도 더 좋은 결과를 얻을 수 있을 것입니다. 301 00:32:40,453 --> 00:32:46,284 다시한번 말씀드리지만 이는 아주 최근에 연구되고 있는 분야입니다. 아주 좋은 질문을 해 주셨습니다. 302 00:32:46,284 --> 00:32:54,354 그러므로 momentum이 좁고 깊은 minima를 무시해 버리는 것은 버그가 아니라 momentum의 특징이라고 할 수 있습니다. 303 00:32:55,979 --> 00:32:59,979 아직 확실하진 않지만(믿거나 말거나) 이는 momentum의 좋은 점이라고 할 수 있겠습니다. 304 00:33:00,825 --> 00:33:04,316 자 그리고 일반 momentum와 Nesterov이 조금 다르게 움직이는 것을 볼 수 있습니다. 305 00:33:04,316 --> 00:33:12,715 이는 Nesterov에서 추가된 수식 때문입니다. 일반 momentum에 비해서 overshooting이 덜 한 것을 알 수 있습니다. 306 00:33:14,683 --> 00:33:20,068 최적화 방법 중에 AdaGrad도 있습니다. 307 00:33:20,068 --> 00:33:25,292 현재 Stanford에 계시는 John Duchi 교수님께서 Ph.D 시절에 제안하신 방법입니다. 308 00:33:25,292 --> 00:33:37,663 AdaGrad는 훈련도중 계산되는 gradients를 활용하는 방법입니다. 309 00:33:39,569 --> 00:33:43,957 Adagrad는 velocity term 대신에 grad squared term을 이용합니다. 310 00:33:43,957 --> 00:33:49,199 그리고 학습 도중에 계산되는 gradient에 제곱을 해서 계속 더해줍니다. 311 00:33:49,199 --> 00:33:57,449 그리고 Update를 할때 Update term을 앞서 계산한 gradient 제곱 항으로 나눠줍니다. 312 00:33:59,334 --> 00:34:07,261 Condition number인 경우 빨간색 박스 안의 값은 어떨까요? 313 00:34:08,393 --> 00:34:12,560 [학생이 대답] 314 00:34:16,256 --> 00:34:22,904 2차원 좌표가 있다고 해 봅시다. 그 중 한 차원은 항상 gradient가 높은 차원입니다. 그리고 다른 하나는 항상 작은 gradient를 가집니다. 315 00:34:22,904 --> 00:34:35,181 Small dimension에서는 gradient의 제곱 값 합이 작습니다. 이 작은 값이 나눠지므로 가속도가 붙게 됩니다. 316 00:34:35,181 --> 00:34:45,924 Large dimension에서는 gradient가 큰 값 이므로 큰 값이 나눠지게 되겠죠. 그러므로 속도가 점점 줄어듭니다. 317 00:34:45,924 --> 00:34:56,093 하지만 AdaGrad에는 문제가 하나 있습니다. 학습이 계속 진행되면 어떻게 될까요? 학습 횟수 t가 계속 늘어나는 것입니다. 318 00:34:56,094 --> 00:34:58,391 [학생이 대답] 319 00:34:58,391 --> 00:35:02,239 AdaGrad는 step을 진행할수록 값이 점점 작아집니다. 320 00:35:02,239 --> 00:35:09,895 update 동안 gradient의 제곱이 계속해서 더해집니다. 때문에 이 값(estimate)은 서서히(monotonically) 증가하게 됩니다. 321 00:35:09,895 --> 00:35:15,359 이는 Step size를 점점 더 작은 값이 되게 합니다. 322 00:35:15,359 --> 00:35:20,334 손실함수가 convex한 경우에 점점 작아지는 것은 정말 좋은 특징이 될 수 있습니다. 323 00:35:20,334 --> 00:35:28,125 convex case에서는 minimum에 근접하면 서서히 속도를 줄여서 수렴할 수 있게 하면 좋겠죠 324 00:35:28,125 --> 00:35:31,192 Convex case에서는 좋은 특징이라 할 수 있습니다. 325 00:35:31,192 --> 00:35:42,007 하지만 non-convex case에서는 문제가 될 수 있습니다. 가령 saddle point에 걸려버렸을 때 AdaGrad는 멈춰버릴 수 있습니다. 326 00:35:42,007 --> 00:35:48,678 AdaGrad의 변형이 RMSProp입니다. 앞서 언급한 문제를 개선시킨 방법입니다. 327 00:35:48,678 --> 00:35:53,390 RMSProp에서는 AdaGrad의 gradient 제곱 항을 그대로 사용합니다. 328 00:35:53,390 --> 00:36:01,085 하지만 이 값들을 그저 누적만 시키는 것이 아니라 기존의 누적 값에 decay_rate를 곱해줍니다. 329 00:36:01,085 --> 00:36:09,340 이 값은 기존의 momentum 수식과 유사하게 생겼습니다. 다만 gradients의 제곱을 계속해서 누적해 나갑니다. 330 00:36:09,340 --> 00:36:20,361 RMSProp에서는 gradient 제곱 항에 쓰는 decay rate는 보통 0.9 또는 0.99정도를 자주 사용합니다. 331 00:36:20,361 --> 00:36:26,601 그리고 '현재 gradient의 제곱'은 (1 - decay rate) 를 곱해줘서 더해줍니다. 332 00:36:26,601 --> 00:36:37,193 RMSProp은 gradient 제곱을 계속 나눠준다는 점에서 AdaGrad와 유사합니다. 333 00:36:37,193 --> 00:36:44,070 이를 통해 step의 속도를 가속/감속 시킬 수 있습니다. 334 00:36:44,070 --> 00:36:52,411 하지만 RMSProp의 경우에는 위와 같은 특징으로 점점 속도가 줄어드는 문제를 해결할 수 있었습니다. 335 00:36:56,455 --> 00:37:04,173 이 예제에서 SGD는 검정색이고 momentum은 파란색 그리고 RMSProp은 빨간색입니다. 336 00:37:04,173 --> 00:37:12,263 RMSProp이나 momentum은 기본 SGD보다는 훨씬 더 좋습니다. 하지만 이 둘의 행동양상은 조금 다릅니다. 337 00:37:12,263 --> 00:37:17,488 momentum의 경우에는 overshoots한 뒤에 다시 minima로 돌아옵니다. 338 00:37:17,488 --> 00:37:26,392 RMSProp은 각 차원마다의 상황에 맞도록 적절하게 궤적(trajectory)을 수정시킵니다. 339 00:37:26,392 --> 00:37:34,412 여러분들한테는 안보이시겠지만 지금 이 그림에는 초록색으로 AdaGrad도 있습니다. 동일한 Learning rate로 말입니다. 340 00:37:34,412 --> 00:37:38,606 하지만 Learning rates가 점차 감소하기 때문에 RMSProp에 가려서 보이지 않습니다. 341 00:37:38,606 --> 00:37:45,553 실제로 AdaGrad는 잘 쓰이지는 않습니다. 그리고 이런 식의 비교는 사실 AdaGrad에게는 불공정합니다. 342 00:37:46,392 --> 00:37:52,558 아마도 AdaGrad의 Learning rate를 늘리게 되면 RMSProp과 비슷한 동작을 할 것입니다. 343 00:37:52,558 --> 00:37:57,148 하지만 일반적으로 Nerural Network를 학습시킬 때 AdaGrad를 잘 사용하지는 않습니다. 344 00:37:57,148 --> 00:37:57,981 질문 있나요? 345 00:37:57,981 --> 00:37:59,796 [학생이 질문] 346 00:37:59,796 --> 00:38:04,387 이 예시에서의 문제는 convex case입니다. (convex인데 왜 Adagrad에게 불리한지) 347 00:38:07,146 --> 00:38:12,003 하지만 learning rates가 서로 상이하기 때문입니다. 348 00:38:12,003 --> 00:38:17,290 때문에 여러 알고리즘 간에 '같은 Learning rates' 를 가지고 AdaGrad 를 visualization하는 것은 공정하지 못합니다. 349 00:38:17,290 --> 00:38:23,132 visualization을 하고자 한다면 알고리즘 별로 learning rates를 조정하는 것이 좋습니다. 350 00:38:27,970 --> 00:38:35,403 자 우리는 momentum이라는 방법을 알아봤습니다. velocity를 이용해서 step을 조절하는 방법이었습니다. 351 00:38:35,403 --> 00:38:43,744 AdaGrad와 RMSProp은 momentum과 다른 방식을 사용하죠. gradients의 제곱을 나눠주는 방식으로 step을 조절했습니다. 352 00:38:43,744 --> 00:38:46,658 이 둘은(momentum 계열 vs Ada계열) 모두 괜찮은 아이디어인 것 같습니다. 353 00:38:46,658 --> 00:38:50,898 그렇다면 이 두 방법을 조합해보면 어떻까요? 아마 훨씬 더 좋은 방법이 될 것 같습니다. 354 00:38:50,898 --> 00:38:56,741 여기 Adam 이라는 알고리즘이 있습니다. 여기 수식은 Adam과 "유사한" 알고리즘이라고 보시면 됩니다. 355 00:38:56,741 --> 00:39:01,119 앞으로 몇 장의 슬라이드를 통해서 '진짜' Adam 이 되도록 조금씩 바꿔 볼 것입니다. 356 00:39:01,119 --> 00:39:06,888 Adam은 first moment와 second moment을 이용해서 이전의 정보(estimate)를 유지시킵니다. 357 00:39:06,888 --> 00:39:14,667 빨간색 first moment는 gradient의 가중 합입니다. 358 00:39:14,667 --> 00:39:22,741 그리고 second moment는 AdaGrad이나 RMSProp처럼 gradients의 제곱을 이용하는 방법입니다. 359 00:39:22,741 --> 00:39:28,621 Adam으로 Update를 진행하게 되면 우선 first moment는 velocity를 담당합니다. 360 00:39:28,621 --> 00:39:37,281 그리고 sqrt(second moment)를 나눠주는데 second moment는 gradient의 제곱 항입니다. 361 00:39:38,128 --> 00:39:46,269 Adam은 마치 RMSProp + momentum 같아 보입니다. 즉 momentum + second squared gradients 이죠 362 00:39:46,269 --> 00:39:51,989 이 두 종류의 유용한 특징을 모두 이용하는 것입니다. 하지만 여기에도 문제가 하나 있습니다. 363 00:39:51,989 --> 00:40:06,134 초기 step 에서는 어떤 일이 발생할까요? 초기에 second moment를 0으로 초기화합니다. 364 00:40:06,134 --> 00:40:16,803 second moment를 1회 Update 하고 난 후를 생각해봅시다. beta2는 decay_rate로 .9또는 .99로 1에 가까운 값입니다. 365 00:40:18,235 --> 00:40:22,867 그렇기 때문에 1회 업데이트 이후에도 second moment는 여전히 0에 가깝습니다. 366 00:40:22,867 --> 00:40:32,377 update step에서 second moment로 나누게 되는데 나눠주는 값이 크기 때문에 초기 step이 엄청나게 커지게 됩니다. 367 00:40:32,377 --> 00:40:37,768 중요한 것은 이 커진 step이 실제로 손실함수가 가파르기 때문(geometry)이 아니라는 것입니다. 368 00:40:37,768 --> 00:40:43,422 이 값은 second moment을 0으로 초기화 시켰기 때문에 발생하는 '인공적인' 현상입니다. 369 00:40:43,422 --> 00:40:44,322 질문 있나요? 370 00:40:44,322 --> 00:40:48,489 [학생이 질문] 371 00:40:52,832 --> 00:41:00,365 first moment도 second moment처럼 초기에 엄청 작은 값일 것입니다. 따라서 372 00:41:00,365 --> 00:41:02,906 learning rate에 '엄청 작은 값'을 곱하고(first moment) '엄청 작은 값의 제곱근(second)'을 나누면 어떻게 될까요? 373 00:41:02,906 --> 00:41:05,746 어쩌면 서로 상쇄시킬 수 있고. 상쇄됀다면 문제는 해결되는 것이죠. 374 00:41:05,746 --> 00:41:13,632 예 사실입니다. 경우에 따라서 서로 상쇄될 수도 있습니다. 하지만 간혹 엄청 큰 step이 발생하는 경우도 생길 수 있습니다. 375 00:41:13,632 --> 00:41:16,245 하지만 한번 발생하면 정말 나쁜 상황일 것입니다. 376 00:41:16,245 --> 00:41:19,533 가령 여러분이 제대로 초기화를 해주지 않아서 아주 큰 step이 발생했다면 377 00:41:19,533 --> 00:41:26,145 초기화가 엉망이 될 것이고 아주 엉뚱한 곳으로 이동할 수도 있습니다. 결국 수렴할 수 없게 될 수도 있습니다. 378 00:41:26,145 --> 00:41:27,165 질문 있나요? 379 00:41:27,165 --> 00:41:30,915 [학생이 질문] 380 00:41:30,915 --> 00:41:37,847 질문은 수식의 10^-7이 무엇인지 입니다. 저 값은 AdaGrad, RMSProp, Adam에서 등장합니다. 381 00:41:37,847 --> 00:41:42,187 우리는 현재 어떤 값으로 '나눗셈' 를 하고 있습니다. 하지만 그 값이 항상 0이 아니라는 보장은 없죠 382 00:41:42,187 --> 00:41:48,609 따라서 분모에 작은 양수 값을 더해줘서 0이 되는 것을 사전에 방지할 수 있습니다. 383 00:41:48,609 --> 00:41:56,012 이 또한 하이퍼파라미터 이긴 하지만 큰 영향력은 없습니다. 보통 10^-7이나 10^-8정도를 사용하면 잘 동작합니다. 384 00:41:57,967 --> 00:42:05,511 Adam은 초기 Step이 엄청 커져 버릴 수 있고 이로 인해 잘못될 수도 있다고 했습니다. 385 00:42:05,511 --> 00:42:12,510 Adam을 이를 해결하기 위해 보정하는 항을 추가합니다. (bias correction term ) 386 00:42:12,510 --> 00:42:22,619 first/second moments를 Update하고 난 후 현재 Step에 맞는 적절한 unbiased term 을 계산해 줍니다. 387 00:42:22,619 --> 00:42:29,550 실제 Adam은 first/second moment만 계산하는 것이 아니라 이렇게 unbiased term을 넣어줘야 합니다. 388 00:42:29,550 --> 00:42:33,167 지금 보시는 부분이 '완전한 Adam' 이라 할 수 있겠습니다. 389 00:42:33,167 --> 00:42:45,550 그리고 Adam은 엄청 좋습니다. 다양한 문제들에도 정말 잘 동작합니다. 저는 어떤 문제에서도 기본 알고리즘으로 Adam을 사용하곤 합니다. 390 00:42:45,550 --> 00:42:53,088 특히나 beta_1 = 0.9, beta_2 = 0.999로 설정하고 Learning rate를 E-3나 E-4 정도로만 설정해 놓으면 391 00:42:53,088 --> 00:42:58,797 거의 모든 아키텍쳐에서 잘 동작하는 기본 설정으로 아주 제격입니다. 392 00:42:58,797 --> 00:43:03,518 일반적으로 Adam으로 시작해 보는 것은 정말 좋습니다. 393 00:43:03,518 --> 00:43:05,949 [웃음] 394 00:43:05,949 --> 00:43:11,634 자 동일한 환경에서 SGD, Momentum, RMSProp, Adam을 한번 비교해 봅시다. 395 00:43:11,634 --> 00:43:18,094 보라색 Adam을 한번 봅시다. momentum과 RMSProp을 짬뽕시켜 놓은듯한 모습입니다. 396 00:43:18,094 --> 00:43:25,175 Adam이 momentum처럼 overshoots하긴 하지만 momentum만큼 엄청 심하지는 않습니다. 397 00:43:25,175 --> 00:43:33,268 그리고 Adam은 RMSProp같은 특징도 가지고 있습니다. 각 차원의 상황을 따로 고려해서 Step을 이동합니다. 398 00:43:33,268 --> 00:43:37,706 여기 단순한 2차원 예제에서 수렴하는 것을 보면 그놈이 그놈같아 보일 수는 있지만 399 00:43:37,706 --> 00:43:42,832 확실한 것은 Adam이 momentum스러우면서도 RMSProp스럽다는 것입니다. 400 00:43:45,042 --> 00:43:48,709 Optimization 알고리즘에 대한 질문 있으신가요? 401 00:43:50,048 --> 00:43:56,606 [학생이 질문] 402 00:43:56,606 --> 00:44:03,193 질문은 Adam이 해결하지 못하는 것은 무엇인지 입니다. Neural networks는 여전이 엄청 크고 학습은 오래걸립니다. 403 00:44:04,744 --> 00:44:07,098 Adam을 쓰더라도 여전히 문제점들이 있습니다. 404 00:44:07,098 --> 00:44:11,979 가령 손실함수가 타원형일 경우를 생각해 봅시다. 405 00:44:11,979 --> 00:44:19,219 Adam을 이용하면 각 차원마다 적절하게 속도를 높히고 줄이면서 '독립적으로' step을 조절할 것입니다. 406 00:44:19,219 --> 00:44:26,576 하지만 이 타원이 축 방향으로 정렬되어 있지 않고 기울어져 있다고 생각해 봅시다. 407 00:44:26,576 --> 00:44:29,887 이 경우에도 Adam은 차원에 해당하는 축 만을 조절할 수 있습니다. 408 00:44:30,935 --> 00:44:38,131 이는 차원을 회전시킨 다음에 수평/수직 축으로만 늘렸다 줄였다 하는 것입니다. 회전을 시킬수는 없죠 409 00:44:38,131 --> 00:44:48,732 이러한 회전된 타원(poor conditioning) 문제는 Adam을 비롯한 다른 여러 알고리즘들도 다룰 수 없는 문제입니다. 410 00:44:51,356 --> 00:44:57,706 지금까지의 모든 Opimization 알고리즘은 learning rate 이라는 하이퍼파라미터를 가지고 있었습니다. 411 00:44:57,706 --> 00:45:01,828 지난 시간이 이 그림을 본 적 있을 것입니다. 412 00:45:01,828 --> 00:45:05,097 Learning rate가 지나치게 높으면 노란색 처럼 솟구치게 되겠죠 413 00:45:05,097 --> 00:45:09,629 파란색 처럼 너무 낮으면 수렴하는데 너무 오래걸립니다. 414 00:45:09,629 --> 00:45:11,933 하지만 learning rate를 잘 고르는 것은 상당히 까다롭습니다. 415 00:45:13,712 --> 00:45:19,308 우리는 학습 과정에서 learning rate 하나를 정해놓고 시작해야 하기 때문에 잘 고르는게 참 어렵습니다. 416 00:45:19,308 --> 00:45:29,705 learning rates dacay 전략을 사용해 볼 수 있습니다. 각각의 learning rates의 특성을 적절히 이용하는 것이죠 417 00:45:29,705 --> 00:45:39,366 처음에는 learning rates를 높게 설정한 다음에 학습이 진행될수록 learning rates를 점점 낮추는 것입니다. 418 00:45:39,366 --> 00:45:46,795 다양한 전략을 시도해 볼 수 있지만 가령 100,000 iter에서 learning rates를 낮추고 학습시키는 것입니다.(step decay) 419 00:45:46,795 --> 00:45:52,579 혹은 exponential decay 처럼 학습과정 동안에 꾸준히 learning rate를 낮출 수도 있습니다. 420 00:45:52,579 --> 00:45:57,598 꾸준히 learning rate를 감소시키는 것에는 다양한 전략이 있을 수 있습니다. 421 00:45:57,598 --> 00:46:04,347 오른쪽의 그림을 보시기 바랍니다. Resnet 논문에 있는 그림입니다. Loss가 계속 내려가고 있습니다. 422 00:46:04,347 --> 00:46:07,898 그리고 어느순간 평평해 지는 듯 하더니 다시 또 내려가는 것을 반복하는 것을 알 수 있습니다. 423 00:46:07,898 --> 00:46:11,312 Resnet 논문에서는 step decay learning rate 전략을 사용한 것입니다. 424 00:46:11,312 --> 00:46:18,401 평평해지다가 갑자기 내려가는 구간은 Learning rate를 낮추는 구간입니다. 425 00:46:18,401 --> 00:46:26,243 learning rate를 언제 낮춰야 하는지를 생각해보면, 현재 수렴을 잘 하고 있는 상황에서 gradient가 점점 작아지고 있는 것입니다. 426 00:46:26,243 --> 00:46:28,066 learning rate가 너무 높아서 더 깊게 들어가지 못합니다. (bouncing around too much) 427 00:46:28,066 --> 00:46:32,745 이 상황에서 learning rate를 낮추게 되면 속도가 줄어들 것이고 지속해서 Loss를 내려갈 수 있을 것입니다. 428 00:46:32,745 --> 00:46:36,475 실제로 상당히 도움이 되는 방법입니다. 429 00:46:36,475 --> 00:46:44,973 그리고 한가지 말씀드릴 것은 learning rate decay는 Adam 보다는 SGD Momentum을 사용할 때 자주 씁니다. 430 00:46:44,973 --> 00:46:50,458 또 한가지 말씀드릴 것은 learning rate decay는 부차적인 (second-order ) 하이퍼파라미터 라는 것입니다. 431 00:46:50,458 --> 00:46:53,324 일반적으로 learning-rate decay를 학습 초기부터 고려하지는 않습니다. 432 00:46:53,324 --> 00:47:00,877 보통 학습 초기에는 learning rate decay가 없다고 생각하고 learning rate를 잘 선택하는 것이 중요합니다. 433 00:47:00,877 --> 00:47:06,068 learning rate와 dacay 등을 cross-validate 하려고 한다면 문제가 너무 복잡해 집니다. 434 00:47:06,068 --> 00:47:10,581 learning rate decay를 설정하는 순서는 우선 decay 없이 학습을 시켜 봅니다. 435 00:47:10,581 --> 00:47:15,427 그리고 Loss curve를 잘 살피고 있다가 decay가 필요한 곳이 어디인지 고려해 보는 것이 좋습니다. 436 00:47:16,860 --> 00:47:24,948 지금까지 배운 Optimization 알고리즘들을 모두 1차미분을 활용한(first-order) 방법이었습니다. 437 00:47:24,948 --> 00:47:33,064 그림처럼 1차원의 손실함수가 있다고 생각해 봅시다. 우리는 지금 빨간색 점에 있는 것입니다. 438 00:47:33,064 --> 00:47:36,057 이 점에서 gradient 를 계산하겠죠 439 00:47:36,057 --> 00:47:40,722 이 gradient 정보를 이용해서 우리는 손실함수를 선형함수로 근사시킵니다. 440 00:47:40,722 --> 00:47:44,208 이는 일종의 1차 테일러 근사입니다. (first-order Taylor apporximation) 441 00:47:44,208 --> 00:47:51,814 우리는 이 1차 근사함수를 실제 손실함수라고 가정하고 Step을 내려갈 것입니다. 442 00:47:51,814 --> 00:47:57,353 하지만 이 근사함수로는 멀리갈 수 없습니다. 443 00:47:57,353 --> 00:48:04,509 현재 우리가 사용하는 정보는 1차 미분값일 뿐입니다. 그리고 우리는 조금 더 괜찮은 방법을 생각해 볼 수도 있을 것입니다. 444 00:48:04,509 --> 00:48:11,248 2차 근사 (second-order approximation)의 정보를 추가적으로 활용하는 방법이 있습니다. 445 00:48:11,248 --> 00:48:18,449 이는 2차 테일러 근사 함수가 될 것이고 이 함수는 2차함수의 모양입니다. 446 00:48:18,449 --> 00:48:22,281 2차 근사를 이용하면 minima에 더 잘 근접할 수 있습니다. you're really happy 447 00:48:22,281 --> 00:48:25,769 이것이 바로 2nd-order optimization의 기본 아이디어입니다. 448 00:48:25,769 --> 00:48:30,489 방금 예시는 다차원으로 확장시켜보면 이를 'Newton step' 이라고 합니다. 449 00:48:30,489 --> 00:48:35,066 Hessian matrix를 계산합니다. 2차 미분값들로 된 행렬입니다. 450 00:48:35,066 --> 00:48:43,689 Hessian matrix의 역행렬을 이용하게 되면 실제 손실함수의 2차 근사를 이용해 minima로 곧장 이동할 수 있을 것입니다. 451 00:48:43,689 --> 00:48:48,910 혹시 이 알고리즘이 다른 Optimization 알고리즘에 비해 특이한 것이 무엇인지 아시겠습니까? 452 00:48:48,910 --> 00:48:51,107 [학생이 대답] 453 00:48:51,107 --> 00:48:54,328 네 맞습니다. Learning rate가 없습니다. That's kind of cool. 454 00:48:56,463 --> 00:49:00,664 지금 우리는 2차근사 함수를 만들었고 이 2차근사 함수의 minima로 이동하는 것입니다. 455 00:49:00,664 --> 00:49:04,681 적어도 "기본적인 Newton's method" 에서는 learning rate는 불필요합니다. 456 00:49:04,681 --> 00:49:07,849 매 step마다 항상 minma를 향해 이동합니다. 457 00:49:07,849 --> 00:49:13,265 하지만 실제로는 learning rate가 필요합니다. 왜냐하면 2차 근사도 사실상 완벽하지 않기 때문이죠 458 00:49:13,265 --> 00:49:21,055 minima로 이동하는게 아니라 'minima의 방향'으로 이동하기 때문이죠 어쨌든 기본버전에는 learning rate가 없습니다. 459 00:49:23,994 --> 00:49:27,366 하지만 불행하게도 Deep learning에서는 사용할 수 없습니다. 460 00:49:27,366 --> 00:49:34,519 왜냐하면 Hessian matrix는 N x N 행렬입니다. N은 Network의 파라미터 수입니다. 461 00:49:34,519 --> 00:49:38,498 N이 1억이면 1억의 제곱만큼 존재할 것입니다. 462 00:49:38,498 --> 00:49:42,046 이를 메모리에 저장할 방법은 없으며 또한 역행렬계산도 불가능 할 것입니다. 463 00:49:42,046 --> 00:49:46,486 그래서 실제로는 'quasi-Newton methods' 를 이용합니다. 464 00:49:46,486 --> 00:49:52,725 Full Hessian을 그대로 사용하기 보다 근사시킵니다. Low-rank approximations 하는 방법입니다. 465 00:49:52,725 --> 00:49:57,092 여러분도 앞으로 간혹 접하게 될 것입니다. 466 00:49:57,092 --> 00:50:03,487 L-BFGS도 second-order optimizer입니다. 이 방법도 Hassian을 근사시켜서 사용하는 방법입니다. 467 00:50:03,487 --> 00:50:11,205 L-BFGS도 여러분이 가끔씩 보게될텐데 사실상 DNN에서는 잘 사용하지 않습니다. 468 00:50:11,205 --> 00:50:16,410 왜냐하면 L-BFGS에서 2차근사가 stochastic case에서 잘 동작하지는 않기 때문입니다. 469 00:50:16,410 --> 00:50:20,616 그리고 L-BFGS는 non-convex problems에도 적합하지 않습니다. 470 00:50:20,616 --> 00:50:23,142 더 깊게는 들어가지 않겠습니다. 471 00:50:23,142 --> 00:50:29,022 실제로는 Adam을 제일 많이 씁니다. 472 00:50:29,022 --> 00:50:38,974 하지만 full batch update가 가능하고 stochasticity이 적은 경우라면 L-BFGS가 좋은 선택이 될 수 있습니다. 473 00:50:38,974 --> 00:50:43,181 L-BFGS가 Neural network를 학습시키는데 그렇게 많이 사용되지는 않지만 474 00:50:43,181 --> 00:50:47,251 앞으로 보게될 Sytle tranfer와 같은 알고리즘에 L-BFGS을 종종 사용할 수 있습니다. 475 00:50:47,251 --> 00:50:54,356 Sytle tranfer같은 stochasticity와 파라미터가 적은 경우에서 Optimization을 해야할 경우에 말이죠 476 00:50:55,834 --> 00:51:00,992 지금까지 이야기했던 모든 것들을 전부 training error를 줄이기 위한 방법들이었습니다. 477 00:51:02,344 --> 00:51:07,452 optimization 알고리즘들은 training error를 줄이고 손실함수를 최소화시키기 위한 역할을 수행합니다. 478 00:51:07,452 --> 00:51:10,403 하지만 사실 우리는 Training error에 크게 신경쓰지 않습니다. 479 00:51:10,403 --> 00:51:13,203 대신에 "한번도 보지 못한 데이터"에 대한 성능이 더 중요하죠 480 00:51:13,203 --> 00:51:16,817 우리가 원하는 것은 train/test error의 격차를 줄이는 것입니다. 481 00:51:16,817 --> 00:51:21,228 질문은 바로 우리가 손실함수 최적화를 이미 모두 끝마친 상황에서 482 00:51:21,228 --> 00:51:25,535 '한번도 보지 못한 데이터' 에서의 성능을 올리기 위해서는 어떻게 해야 할까요? 483 00:51:28,497 --> 00:51:33,617 가장 빠르고 쉬운 길은 바로 모델 앙상블입니다. 484 00:51:33,617 --> 00:51:36,767 Machine learning 분야에서 종종 사용하는 기법입니다. 485 00:51:36,767 --> 00:51:44,588 아이디어는 아주 간단합니다. 모델을 하나만 학습시키지 말고 10개의 모델을 독립적으로 학습시키는 것입니다. 486 00:51:44,588 --> 00:51:51,333 결과는 10개 모델 결과의 평균을 이용합니다. 487 00:51:53,562 --> 00:52:01,555 모델의 수가 늘어날수록 overfitting 줄어들고 성능이 조금씩 향상됩니다. 보통 2%정도 증가하죠 488 00:52:01,555 --> 00:52:05,302 엄청나게 큰 변화는 아니지만 상당히 일관적으로 이 정도 늘어납니다. 489 00:52:05,302 --> 00:52:13,263 Imagenet 같은 대회에서는 모델의 성능을 최대화 시키기 위해서 이러한 앙상블 기법을 사용하는 모습을 볼 수 있습니다. 490 00:52:14,488 --> 00:52:20,482 조금 더 창의적인 방법도 있습니다. 모델을 독립적으로 학습시키는 것이 아니라 491 00:52:20,482 --> 00:52:25,928 학습 도중 중간 모델들을 저장(sanpshots)하고 앙상블로 사용할 수 있습니다. 492 00:52:25,928 --> 00:52:29,804 그리고 Test time에는 여러 snapshots에서 나온 예측값들을 평균을 내서 사용합니다. 493 00:52:29,804 --> 00:52:33,244 이런 snapshots은 Training 과정 중간에 저장하는 것입니다. 494 00:52:34,133 --> 00:52:43,210 이번주에 ICLR에 좀 더 향상된 앙상블 알고리즘이 발표되었습니다. 이 방법은 아주 독특한 Learning rate 스케줄을 이용합니다. 495 00:52:43,210 --> 00:52:47,996 Learning rate를 엄청 낮췄다가 다시 엄청 높혔다가를 반복합니다. 496 00:52:47,996 --> 00:52:57,631 이 논문의 아이디어는 이런 방식으로 손실함수에 다양한 지역에 수렴할 수 있도록 만들어 줍니다. 497 00:52:58,717 --> 00:53:05,532 이런 앙상블 기법으로 모델을 한번만 Train시켜도 좋은 성능을 얻을 수 있게 하는 방법입니다. 498 00:53:05,532 --> 00:53:11,198 질문있나요? 499 00:53:25,388 --> 00:53:33,413 질문은 모델간의 Loss 차이가 크면 한쪽이 overfiting 일 수 있으니 별로 안좋고, 또 차이가 작아도 안좋지 않냐는 것입니다. 500 00:53:33,413 --> 00:53:37,446 그러니 좋은 앙상블 결과를 위해서라면 모델 간의 최적의 갭을 찾는 것이 중요하지 않느냐는 것입니다. 501 00:53:37,446 --> 00:53:39,132 사실 갭이 중요한 것이 아닙니다. 502 00:53:39,132 --> 00:53:44,019 중요한 것은 validation set의 성능을 최대화시키는 것입니다. 503 00:53:44,019 --> 00:53:54,995 하지만 우선 갭을 신경쓰지 않고 모델을 조금 더 Overfitting 시킬 수 있다면 아마 더 좋은 성능을 낼 수 있을 것입니다. 504 00:53:54,995 --> 00:54:02,720 Validation set 성능과 이 갭 사이에는 묘한 관계가 있긴 하지만 오로지 Validation set 성능만 신경쓰면 됩니다. 505 00:54:02,720 --> 00:54:03,735 질문있나요? 506 00:54:03,735 --> 00:54:07,004 [학생이 질문] 507 00:54:07,004 --> 00:54:09,528 질문은 앙상블 모델마다 하이퍼파라미터를 동일하게 줘야 하는지 입니다. 508 00:54:09,528 --> 00:54:12,234 좋은 질문이군요. 그렇지 않을 수도 있습니다. 509 00:54:12,234 --> 00:54:19,614 다양한 "모델 사이즈", "learning rate", 그리고 "다양한 regularization 기법" 등을 앙상블 할 수 있습니다. 510 00:54:19,614 --> 00:54:22,614 실제로 그렇게 사용하기도 합니다. 511 00:54:23,496 --> 00:54:31,769 또 다른 방법으로는 학습하는 동안에 파라미터의 exponentially decaying average를 계속 계산합니다. 512 00:54:31,769 --> 00:54:35,778 이 방법은 학습중인 네트워크의 smooth ensemble 효과를 얻을 수 있습니다. 513 00:54:35,778 --> 00:54:41,649 checkpoints에서의 파라미터를 그대로 쓰지 않고 smoothly decaying average를 사용하는 방법입니다. 514 00:54:41,649 --> 00:54:45,262 이를 Polyak averaging라고 합니다. 때때로 조금의 성능향상을 보일 수 있습니다. 515 00:54:45,262 --> 00:54:50,838 이 또한 시도해볼만한 방법이긴 하지만 실제로 자주 사용하지는 않습니다. 516 00:54:50,838 --> 00:54:55,778 그렇다면 앙상블이 아닌 단일 모델의 성능을 향상시키기 위해서는 어떻게 해야 할까요? 517 00:54:57,229 --> 00:55:02,503 앙상블을 하려 한다면 test time에 10개의 모델을 돌려야 할 수도 있습니다. 그렇게 좋은 방법은 아니죠 518 00:55:02,503 --> 00:55:06,219 단일 모델의 성능을 올리는 것이 우리가 정말 원하는 것입니다. 519 00:55:06,219 --> 00:55:08,237 바로 regularization입니다. 520 00:55:08,237 --> 00:55:11,954 우리가 모델에 어떤 것을 추가할 텐데 모델이 training data에 fit하는 것을 막아줄 것입니다. 521 00:55:11,954 --> 00:55:16,203 그리고 한번도 보지 못한 데이터에서의 성능을 향상시키는 방법입니다. 522 00:55:16,203 --> 00:55:23,515 우리는 이미 몇 가지 regularization 기법을 살펴봤습니다. Loss에 추가적인 항을 삽입하는 방법이었습니다. 523 00:55:23,515 --> 00:55:29,738 손실함수에서 기존의 항은 training data에 fit하려 하고 다른 하나는 regularization term 이죠 524 00:55:29,738 --> 00:55:33,032 과제에서도 있었죠 L2 regularization이 대표적인 예입니다. 525 00:55:34,804 --> 00:55:43,001 앞서 강의에서도 말씀드렸듯이 L2 regularization은 Neural networks에는 잘 어울리지 않습니다. 526 00:55:43,922 --> 00:55:47,982 때문에 조금 다른 것을 사용하죠 527 00:55:47,982 --> 00:55:53,376 Neural network에서 가장 많이 사용하는 regularization은 바로 dropout입니다. 528 00:55:53,376 --> 00:55:55,080 Dropout은 정말 간단합니다. 529 00:55:55,080 --> 00:56:02,264 forward pass 과정에서 임의로 일부 뉴런을 0으로 만드는 것입니다. 530 00:56:02,264 --> 00:56:08,688 forward pass 할때마다 0이 되는 뉴런이 바뀝니다. Dropout은 한 레이어씩 진행하게 됩니다. 531 00:56:08,688 --> 00:56:15,193 한 레이어의 출력을 전부 구합니다. 그리고 임의로 일부를 0으로 만듭니다. 그리고 다음 레이어로 넘어가는 식입니다. 532 00:56:15,193 --> 00:56:22,445 왼쪽에는 dropout이 없고 오른쪽은 dropout이 적용된 경우 입니다. 533 00:56:22,445 --> 00:56:30,400 오른쪽 모델은 동일한 네트워크의 더 작아진 버전 처럼 생겼습니다. 오로지 뉴런의 일부만 사용하고 있습니다. 534 00:56:30,400 --> 00:56:35,746 forward pass iteration 마다 그 모양은 계속 바뀝니다. 535 00:56:35,746 --> 00:56:36,732 질문 있나요? 536 00:56:36,732 --> 00:56:40,899 [학생이 질문] 537 00:56:43,694 --> 00:56:46,375 질문은 지금 무엇을 0으로 놓는 것인지 입니다. activations을 0으로 설정하는 것입니다. 538 00:56:46,375 --> 00:56:51,731 각 레이어에서 next activ= prev activ * weight 죠 539 00:56:51,731 --> 00:57:01,592 현재 activations의 일부를 0으로 만들면 다음 레이어의 일부는 0과 곱해질 것입니다. 540 00:57:01,592 --> 00:57:03,155 질문 있나요? 541 00:57:03,155 --> 00:57:06,702 [학생이 질문] 542 00:57:06,702 --> 00:57:08,751 질문은 어떤 종류의 레이어에서 이를 사용하는지 입니다. 543 00:57:08,751 --> 00:57:14,454 Dropout은 fc layer에서 흔히 사용합니다. 하지만 conv layers에서도 종종 볼 수 있습니다. 544 00:57:14,454 --> 00:57:23,423 Conv net의 경우에서는 전체 feature map에서 dropout을 시행합니다. 545 00:57:24,455 --> 00:57:30,117 conv layer의 경우에 여러 channels이 있기 때문에 일부 channel 자체를 dropout 시킬 수도 있겠습니다. 546 00:57:32,059 --> 00:57:38,480 실제로 Dropout 구현은 아주 쉽습니다. 두 줄이면 충분합니다. 547 00:57:38,480 --> 00:57:41,572 여기 3-layer neural network 예제가 있습니다. 여기에 Dropout을 추가했습니다. 548 00:57:41,572 --> 00:57:49,460 임의로 0으로 설정하는 부분만 추가하면 됩니다. 구현하기 아주 쉽습니다. 549 00:57:49,460 --> 00:57:52,138 그렇다면 dropout이 도대체 왜 좋을까요? 550 00:57:52,138 --> 00:57:58,067 일부 값들을 0으로 만들면서 training time의 네트워크를 심각하게 훼손시키고 있습니다. 551 00:57:58,067 --> 00:58:00,988 이런 일이 어떻게 가능할까요? 552 00:58:00,988 --> 00:58:08,532 대략적으로 말씀드리면, 특징들 간의 상호작용(co-adaptation)을 방지한다고 볼 수 있습니다. 553 00:58:09,622 --> 00:58:15,853 자 우선 우리에게 고양이를 분류하는 어떤 네트워크가 있다고 해봅시다. 554 00:58:15,853 --> 00:58:21,066 어떤 뉴런은 눈에대해, 어떤 뉴런은 꼬리에대해, 또 어떤 뉴런은 고양이의 털에 대해 학습하는 것을 상상해 볼 수 있을 것입니다. 555 00:58:21,066 --> 00:58:24,751 그리고 이 이미지가 고양이인지 아닌지를 이 정보들을 모두 취합해서 결정을 내리는 것입니다. 556 00:58:24,751 --> 00:58:32,831 Dropout을 적용하게 되면 네트워크가 어떤 일부 features에만 의존하지 못하게 해줍니다. 557 00:58:32,831 --> 00:58:37,725 대신에 모델이 "고양이다" 라고 예측할 때 다양한 features를 골고루 이용할 수 있도록 합니다. 558 00:58:37,725 --> 00:58:42,205 따라서 Dropout이 Overfitting을 어느정도 막아준다고 할 수 있겠습니다. 559 00:58:42,205 --> 00:58:50,347 그리고 최근 Dropout에 대한 새로운 해석이 나왔는데 단일 모델로 앙상블 효과를 가질 수 있다는 것입니다. 560 00:58:51,690 --> 00:58:58,745 자 여기 왼쪽의 Dropout을 적용한 네트워크를 살펴보면 뉴런의 일부만 사용하는 서브네트워크라는 것을 알 수 있습니다. 561 00:58:58,745 --> 00:59:03,391 Dropout으로 만들 수 있는 서브네트워크의 경우의 수가 정말 다양하다는 것을 알 수 있습니다. 562 00:59:03,391 --> 00:59:09,145 따라서 Dropout은 서로 파라미터를 공유하는 서브네트워크 앙상블을 동시에 학습시키는 것이라고 생각할 수 있습니다. 563 00:59:09,145 --> 00:59:13,790 하지만 뉴런의 수에 따라서 앙상블 가능한 서브네트워크의 수가 기하급수적으로 증가하기 때문에 564 00:59:13,790 --> 00:59:17,152 가능한 모든 서브네트워크를 사용하는것은 사실상 불가능합니다. 565 00:59:18,089 --> 00:59:24,788 Dropout은 아주 거대한 앙상블 모델을 동시에 학습 시키는 것이라고 볼 수 있겠습니다. 566 00:59:25,622 --> 00:59:29,128 그렇다면 Dropout을 사용하면 Test time에 어떤 일이 일어날까요? 567 00:59:29,128 --> 00:59:34,158 Dropout을 사용하게되면 기본적으로 Neural network의 동작 자체가 변하게 됩니다. 568 00:59:34,158 --> 00:59:42,850 기존의 Neural network는 가중치 w와 입력 x에 대한 함수(f) 였습니다. 569 00:59:42,850 --> 00:59:48,268 하지만 Dropout을 사용하면 Network에 z라는 입력이 추가됩니다. z는 "random dropout mask" 입니다. 570 00:59:48,268 --> 00:59:52,732 z는 random입니다. 하지만 test time에 임의의 값을 부여하는 것은 좋지 않습니다. 571 00:59:52,732 --> 00:59:57,444 가령 여러분이 Facebook에서 일하고 있고 사람들이 업로드하는 이미지를 분류하려 한다고 해봅시다. 572 00:59:57,444 --> 01:00:03,092 오늘은 고양이라고 분류했던 이미지를 내일이 되서는 다른 이미지라고 분류한다고 하면 그닥 좋지 않은 상황이겠죠 573 01:00:03,092 --> 01:00:09,323 따라서 네트워크가 이미 학습된 네트워크의 Test time에는 이러한 임의성(stochasticity)은 적절하지 않습니다. 574 01:00:09,323 --> 01:00:12,093 대신 그 임의성(randomness)을 average out 시킵니다. 575 01:00:12,093 --> 01:00:18,131 이는 적분을 통해 randomness를 marginalize out시키는 것으로 한번 생각해 볼 수 있을 것입니다. 하지만 실제로는- 576 01:00:18,131 --> 01:00:24,368 이 적분을 다루기는 상당히 까다롭습니다. 577 01:00:24,368 --> 01:00:28,073 이 문제를 해결할 수 있는 간단한 방법 중 하나는 샘플링을 통해서 적분을 근사시키는 것인데요 578 01:00:28,073 --> 01:00:31,484 z를 여러번 샘플링해서 test time에 이를 average out 시키는 것입니다. 579 01:00:31,484 --> 01:00:36,040 하지만 이 방법도 Test time에서의 randomness을 만들어 내기 때문에 좋지 않은 방법입니다. 580 01:00:36,040 --> 01:00:41,423 고맙게도 dropout의 경우에는 일종의 locally cheap한 방법을 이용해서 이 적분식을 근사화시킬 수 있습니다. 581 01:00:41,423 --> 01:00:47,228 가령 여기 하나의 뉴런이 있습니다. 출력은 a 이고 입력 x, y가 있고 가중치 w_1, w_2가 있습니다. 582 01:00:47,228 --> 01:00:52,622 Test time에서 a는 w_1x + w_2y 입니다. 583 01:00:53,590 --> 01:01:00,645 자 그럼 이 네트워크를 dropout(p = 0.5) 를 적용해서 train 시킨다고 생각해 봅시다. 584 01:01:00,645 --> 01:01:06,317 train time에서의 기댓값은 아래와 같은 경우로 (analytically) 계산해 볼 수 있습니다. 585 01:01:07,712 --> 01:01:12,249 dropout mask에는 4가지 경우의 수가 존재합니다. 이제 그 값들을 4개의 마스크에 대해 평균화 시켜 줍니다. 586 01:01:12,249 --> 01:01:18,204 Train time에서 a의 기댓값은 1/2(w_1x + w_2y) 입니다. 587 01:01:19,075 --> 01:01:29,000 이 부분에서 test/train time 간의 기댓값이 서로 상이합니다. train time의 기댓값은 test time의 절반밖에 안되죠 588 01:01:29,000 --> 01:01:34,883 Test time에서 stochasticity를 사용하지 않고 할 수 있는 값 싼(cheap) 방법 중 하나는 589 01:01:34,883 --> 01:01:40,736 대신에 dropout probability를 네트워크의 출력에 곱합니다. 자 이제 둘의 기댓값이 같아졌습니다. 590 01:01:40,736 --> 01:01:44,733 이 방법은 이전의 복잡한 적분식을 아주 저렴하게(cheap) local approximation시킬 수 있는 방법입니다. 591 01:01:44,733 --> 01:01:48,576 실제로 많은 사람들이 Dropout을 사용할 때 이 방법을 많이 사용합니다. 592 01:01:49,715 --> 01:01:56,269 Dropout을 사용하게 되면 네트워크 출력에 dropout probability를 곱해줘야 합니다. 593 01:01:56,269 --> 01:01:59,393 Dropout에 대해 요약해보자면 Forward pass에 Dropout 을 추가시키는 것은 상당히 간단합니다. 594 01:01:59,393 --> 01:02:03,807 일부 노드를 무작위로 0으로 만들어주는데는 2줄이면 충분하죠 595 01:02:03,807 --> 01:02:10,209 그리고 Test time에서는 그저 값 하나만 곱해주면 됩니다. (probability) 596 01:02:10,209 --> 01:02:16,613 Dropout은 상당히 간단합니다. 그리고 Neural network의 Regularization에 상당히 효과적이죠 597 01:02:16,613 --> 01:02:21,454 그리고 Dropout을 사용할 때 한가지 트릭을 생각해 볼 수 있습니다. Dropout을 역으로 계산하는 것입니다 (inverted dropout) 598 01:02:22,665 --> 01:02:28,735 Test time에는 곱하기 연산이 하나 추가되는 것은 상당히 신경쓰이는 일입니다. Test time에서는 계산효율이 중요합니다 599 01:02:28,735 --> 01:02:37,677 Test time에는 기존의 연산을 그대로 사용하고 대신 Train time 에서 p를 나눠줍니다. 보통 train은 GPU로 하기 때문이죠 600 01:02:37,677 --> 01:02:44,733 Train time에서는 곱하기 몇 번 추가되는 것에 별로 신경쓰지 않지만 Test time에서는 가능한 효율적으로 동작하길 원합니다. 601 01:02:44,733 --> 01:02:45,566 질문 있나요? 602 01:02:46,416 --> 01:02:56,777 [학생이 질문] 603 01:02:57,678 --> 01:03:02,212 질문은 dropout을 사용하게 되면 Train time에서 gradient에는 어떤 일이 일어나는지 입니다. 604 01:03:02,212 --> 01:03:06,583 Dropout이 0으로 만들지 않은 노드에서만 Backprop이 발생하게 됩니다. 605 01:03:06,583 --> 01:03:15,356 때문에 dropout을 사용하게 되면 전체 학습시간이 늘어납니다. 각 스텝마다 업데이드되는 파라미터의 수가 줄어들기 때문이죠 606 01:03:15,356 --> 01:03:22,287 다시 말해 Dropout을 사용하게 되면 전체 학습시간은 늘어나지만 모델이 수렴한 후에는 더 좋은 일반화 능력을 얻을 수 있습니다. 607 01:03:24,409 --> 01:03:32,810 사실 Dropout은 여기 보이는 일반적인 regularization 전략을 구체화시킨 하나의 예시에 불과합니다. 이 전략은 - 608 01:03:32,810 --> 01:03:37,482 Train time에는 네트워크에 무작위성(randomness)을 추가해 training data에 너무 fit하지 않게 합니다. 609 01:03:37,482 --> 01:03:41,037 네트워크를 마구잡이로 흩뜨려 놓으므로써 training data에 fit하는 것을 방해하는 것입니다. 610 01:03:41,037 --> 01:03:46,160 그리고 Test time에서는 randomness을 평균화 시켜서 generalization 효과를 주는 것입니다. 611 01:03:46,160 --> 01:03:53,927 Dropout이 Regularization에 가장 대표적인 예이긴 하지만 Batch normalization 또한 이와 비슷한 동작을 할 수 있습니다. 612 01:03:53,927 --> 01:04:00,755 Train time의 BN를 상기해보면 mini batch로 하나의 데이터가 샘플링 될 때 매번 서로 다른 데이터들과 만나게 됩니다. 613 01:04:00,755 --> 01:04:07,200 Train time에서는 각 데이터에 대해서 이 데이터를 얼마나 어떻게 정규화시킬 것인지에 대한 stochasticity이 존재했습니다. 614 01:04:07,200 --> 01:04:14,735 하지만 test time에서는 정규화를 mini batch 단위가 아닌 global 단위로 수행함으로써 stochasticity를 평균화 시킵니다. 615 01:04:14,735 --> 01:04:20,223 이런 특성 때문에 BN 은 Dropout과 유사한 Regularization 효과를 얻을 수 있었습니다. 616 01:04:20,223 --> 01:04:25,478 Train time에는 stochasticity(noise)가 추가되지만 Test time에서는 전부 평균화 되기 때문입니다. 617 01:04:25,478 --> 01:04:35,744 실제로 BN을 사용할 때는 Dropout을 사용하지 않습니다. BN에도 충분히 regularization 효과가 있기 때문이죠 618 01:04:35,744 --> 01:04:43,833 하지만 여전히 Dropout은 쓸모 있습니다. 우리가 자유롭게 조절할 수 있는 파라미터 p가 있기 때문이죠. BN에는 없는 것이죠 619 01:04:43,833 --> 01:04:48,928 이러한 Regularization 패러다임에 부합하는 또 한가지 전략은 바로 data augmentation 입니다. 620 01:04:48,928 --> 01:04:57,078 기본 버전의 학습과정에서는 데이터가 있고 레이블이 있고 이를 통해 매 스텝 CNN을 업데이트했습니다. 621 01:04:57,078 --> 01:05:03,555 하지만 그 대신 train time에 이미지를 무작위로 변환시켜 볼 수 있겠습니다. 레이블은 그대로 놔둔 채로 말입니다. 622 01:05:03,555 --> 01:05:09,418 이제 우리는 원본 이미지를 사용하는 것이 아니라 무작위로 변환시킨 이미지로 학습시키게 되는 것입니다. 623 01:05:09,418 --> 01:05:16,153 가령 이미지가 horizontal flips 할 수 있겠습니다. 이미지가 반전되도 고양이는 여전히 고양이죠 624 01:05:17,690 --> 01:05:23,763 혹은 이미지를 임의의 다양한 사이즈로 잘라서(crop) 사용할 수도 있습니다. 그래도 여전히 이미지는 고양이죠 625 01:05:25,188 --> 01:05:30,317 자 그럼 test time에서 stochasticity를 average out 시키는 것을 한번 생각해봅시다. 626 01:05:30,317 --> 01:05:34,309 "네개의 각 코너" 와 "중앙" 에서 잘라낸 이미지와 이들의 "반전 이미지"를 사용합니다. 627 01:05:34,309 --> 01:05:38,041 ImageNet 관련 모델들의 논문을 읽어보면 저자들이 보통 하나의 이미지를 그대로 사용했을 때의 성능과 628 01:05:38,041 --> 01:05:47,308 이미지 한장에서 10개를 잘라내서의 성능을 비교하곤 합니다. *10개 = (4개코너 + 중앙) x (그냥 + 반전) 629 01:05:48,238 --> 01:05:56,345 Data augmentation으로 color jittering도 있습니다. 학습 시 이미지의 contrast 또는 brightness를 바꿔줍니다. 630 01:05:56,345 --> 01:06:04,642 color jittering에는 조금 더 복잡한 방법도 있습니다. PCA의 방향을 고려하여 color offset을 조절하는 방법입니다. 631 01:06:04,642 --> 01:06:11,456 이 방법은 color jittering을 좀 더 data-dependent한 방법으로 진행하는 것입니다. 자주 사용하는 방법은 아닙니다. 632 01:06:12,492 --> 01:06:18,037 일반적으로 data augmentation는 어떤 문제에도 적용해 볼 수 있는 아주 "일반적인 방법" 이라고 할 수 있습니다. 633 01:06:18,037 --> 01:06:24,940 어떤 문제를 풀려고 할 때, 이미지의 label을 바꾸지 않으면서 이미지를 변환시킬 수 있는 많은 방법들을 생각해 볼 수 있습니다. 634 01:06:24,940 --> 01:06:31,218 Train time에 입력 데이터에 임의의 변환을 시켜주게 되면 일종의 regularization 효과를 얻을 수 있습니다. 635 01:06:31,218 --> 01:06:38,954 그 이유를 다시 말씀드리면 train time에는 stochasticity가 추가되고 test time에는 marginalize out 되기 때문이죠 636 01:06:40,055 --> 01:06:45,232 지금까지 세 가지의 예시를 살펴보았습니다. dropout, batch normalization, data augmentation 이죠 637 01:06:45,232 --> 01:06:47,154 하지만 또 다른 많은 방법들이 존재합니다. 638 01:06:47,154 --> 01:06:53,049 여러분들도 Regularization의 패턴을 잘 숙지하고 논문을 읽다보면 그런 방법들이 눈에 잘 들어올 것입니다. 639 01:06:53,049 --> 01:06:56,722 Dropout과 유사한 방법이 하나 더 있습니다. DropConnect라는 방법이죠 640 01:06:56,722 --> 01:07:06,265 DropConnect은 activation이 아닌 weight matrix를 임의적으로 0으로 만들어주는 방법입니다. 641 01:07:06,265 --> 01:07:09,652 Dropout과 동작도 아주 비슷합니다. 642 01:07:09,652 --> 01:07:16,281 그리고 또 한가지 방법이 있습니다. 사람들이 자주 쓰지는 않지만 개인적으로 아주 좋은 아이디어라고 생각합니다. 643 01:07:16,281 --> 01:07:19,400 fractional max pooling 이라는 방법입니다. 644 01:07:19,400 --> 01:07:29,067 보통 2x2 maxpooling 연산은 고정된 2x2 지역에서 수행합니다. 하지만 fractional max pooling에서는 그렇게 하지 않고 645 01:07:29,067 --> 01:07:35,851 pooling연산을 수행 할 지역이 임의로 선정됩니다. 646 01:07:35,851 --> 01:07:43,070 여기 오른쪽 예시를 보시면 Train time에 샘플링될 수 있는 임의의 pooling region을 보실 수 있습니다. 647 01:07:43,070 --> 01:07:48,857 그리고 test time에 stochasticity를 average out 시키려면 648 01:07:48,857 --> 01:07:54,704 pooling regions를 고정시켜 버리거나 혹은 여러개의 pooling regions을 만들고 averaging over시킵니다. 649 01:07:54,704 --> 01:07:59,027 많이 사용하는 방법은 아니지만 참 좋은 아이디어입니다. 650 01:07:59,027 --> 01:08:05,890 Regularization pattern이라는 패러다임에서 봤을때 아주 놀랄만한 논문이 작년(2016)에 나왔습니다. 651 01:08:05,890 --> 01:08:09,911 올해 강의에 새롭게 소개시켜 드리는 논문입니다. stochastic depth에 관련한 논문이죠 652 01:08:09,911 --> 01:08:15,490 왼쪽의 네트워크를 한번 보시죠 우리에게 아주 깊은 네트워크가 있다고 해봅시다. 653 01:08:15,490 --> 01:08:18,530 train time에 네크워크의 레이어를 randomly drop합니다. 654 01:08:18,530 --> 01:08:24,113 Train time에는 layer 중 일부를 제거해 버리고 일부만 사용해서 학습합니다. 655 01:08:24,114 --> 01:08:26,854 그리고 test time에는 전체 네트워크를 다 사용합니다. 656 01:08:26,854 --> 01:08:30,251 정말 놀라운 연구가 아닐 수 없습니다. 657 01:08:30,251 --> 01:08:35,310 하지만 이 방법의 regularization 효과는 dropout과 같은 다른 방법들과 유사합니다. 658 01:08:35,310 --> 01:08:42,041 그렇지만 아주 놀랍고 아주 최신의 연구이며(cutting-edge) 실제로 잘 사용하진 않지만 아주 좋은 아이디어입니다. 659 01:08:44,694 --> 01:08:52,673 regularization에 대해서 질문 있으신가요? 660 01:08:52,673 --> 01:08:57,046 [학생이 질문] 661 01:08:57,046 --> 01:09:01,184 질문은 보통 하나 이상의 regularization 방법을 사용하는지 입니다. 662 01:09:04,325 --> 01:09:09,751 일반적으로는 batch normalization를 많이 사용합니다. 대부분의 네트워크에서 보통 잘 동작하기 때문이죠 663 01:09:09,752 --> 01:09:12,650 아주 깊은 네트워크에서도 수렴을 잘 하도록 도와줍니다. 664 01:09:12,650 --> 01:09:25,204 대게는 BN만으로 충분합니다만 overfitting이 발생한다 싶으면 Dropout과 같은 다양한 방법을 추가해 볼 수 있습니다. 665 01:09:25,204 --> 01:09:28,526 보통은 이를 가지고 blind cross-validation 를 수행하지는 않습니다. 666 01:09:28,526 --> 01:09:33,942 대신에 네트워크에 overfit의 조짐이 보일때 하나씩 추가시켜 보는 것입니다. 667 01:09:36,400 --> 01:09:38,981 모델을 빠르게 학습시킬 수 있는 방법 중에는 transfer learning이 있습니다. 668 01:09:38,981 --> 01:09:47,018 지금까지는 regularization를 배웠습니다. 다양한 전략으로 train/test error간의 격차를 줄여보려는 것이었죠 669 01:09:48,903 --> 01:09:53,012 overfitting이 일어날 수 있는 상황중 하나는 바로 충분한 데이터가 없을 때 입니다. 670 01:09:53,012 --> 01:10:00,444 우리는 엄청 크고 파워풀한 모델을 원할지 모르겠지만 그 모델은 아주 작은 데이터셋을 지나치게 overfit할 수 있습니다. 671 01:10:00,444 --> 01:10:05,909 Regularization이 이를 해결할 수 있는 전략 중 하나입니다만 Transfer learning 이라는 방법도 있습니다. 672 01:10:05,909 --> 01:10:12,730 Transfer learning은 "CNN 학습에는 엄청많은 데이터가 필요함" 이라는 미신을 무너뜨려버립니다. 673 01:10:12,730 --> 01:10:15,300 아이디어는 정말 간단합니다. 674 01:10:15,300 --> 01:10:20,798 우선 여기 CNN모델이 있다고 해봅시다. VGG스럽게 생긴 모델입니다. 675 01:10:20,798 --> 01:10:25,031 이 CNN을 가지고 우선은 ImageNet과 같은 아주 큰 데이터셋으로 학습을 한번 시킵니다. 676 01:10:25,031 --> 01:10:28,039 이정도 데이터셋이면 전체 네트워크를 학습시키기에 충분한 양입니다. 677 01:10:28,039 --> 01:10:34,596 자 이제 할 일은 Imagenet에서 학습된 features를 우리가 가진 작은 데이터셋에 적용하는 것입니다. 678 01:10:34,596 --> 01:10:42,864 이제는 1000개의 ImageNet 카테고리를 분류하는 것이 아니라 10종의 강아지를 분류하는 문제입니다. 데이터는 엄청 적습니다. 679 01:10:42,864 --> 01:10:45,917 이 작은 데이터셋은 C개의 클래스만 가지고있습니다.(10개) 680 01:10:45,917 --> 01:10:58,135 일반적인 절차는, 우선 가장 마지막의 FC Layer는 최종 feature와 class scores간의 연결인데 이를 초기화시킵니다. 681 01:10:59,651 --> 01:11:02,952 기존에 ImageNet을 학습시킬 때는 4,096 x 1,000 차원의 행렬이었습니다. 682 01:11:02,952 --> 01:11:09,182 하지만 우리의 새로운 문제를 풀기 위해서 4,096 x 10(C)으로 바꿔주게 됩니다. 683 01:11:09,182 --> 01:11:13,985 그리고 방금 정의한 가중치 행렬은 초기화시킵니다. 그다음 나머지 이전의 모든 레이어들의 가중치는 freeze시킵니다. 684 01:11:13,985 --> 01:11:21,947 그렇게 되면 linear classifier를 학습시키는 것과 같습니다. 오로지 마지막 레이어만 가지고 우리 데이터를 학습시키는 것입니다. 685 01:11:23,788 --> 01:11:28,756 이 방법은 사용하면 아주 작은 데이터셋일지라도 아주 작 동작하는 모델을 만들 수 있습니다. 686 01:11:28,756 --> 01:11:35,166 만일 데이터가 조금 더 있다면 전체 네트워크를 fine-tuning 할 수 있습니다. 687 01:11:35,166 --> 01:11:44,935 최종 레이어들을 학습시키고 나면, 네트워크의 일부만이 아닌 네트워크 전체의 학습을 고려해 볼 수도 있을 것입니다. 688 01:11:44,935 --> 01:11:49,434 데이터가 더 많이 있다면 네트워크의 더 많은 부분을 업데이트 시킬 수 있을지도 모릅니다. 689 01:11:49,434 --> 01:11:56,143 이 부분에서는 보통 기존의 Learning rate보다는 낮춰서 학습시킵니다. 690 01:11:56,143 --> 01:12:02,973 왜냐하면 기존의 가중치들이 이미 ImageNet으로 잘 학습되어 있고 이 가중치들이 대게는 아주 잘 동작하기 때문입니다. 691 01:12:02,973 --> 01:12:08,605 우리가 가진 데이터셋에서의 성능을 높히기 위해서라면 그 가중치들을 아주 조금씩만 수정하면 될 것입니다. 692 01:12:08,605 --> 01:12:15,490 따라서 transfer learning을 수행 함에 있어서 이렇게 생긴 2 x 2의 격자 시나리오를 예상해 볼 수 있을 것입니다. 693 01:12:15,490 --> 01:12:20,113 우선 아주 적은 양의 데이터셋이 있는 경우와 아주 많은 양의 데이터셋이 있는 경우가 있겠죠 694 01:12:21,188 --> 01:12:28,780 그리고 이전에 학습된 데이터셋과 현재 데이터셋이 얼마나 유사한지의 경우도 생각해 볼 수 있습니다. 695 01:12:28,780 --> 01:12:35,335 기존의 데이터와 유사한 경우라면 아주 순조로운 출발입니다. 696 01:12:35,335 --> 01:12:48,861 가령 현재의 데이터셋이 ImageNet와 유사하지만 소량의 경우라면, 기존 모델의 마지막 레이어만 학습시켜 볼 수 있겠습니다 697 01:12:48,861 --> 01:12:54,786 데이터가 그보다는 조금 많다고 생각이 되면 모델 전체를 fine tuning해 볼 수도 있을 것입니다. 698 01:12:54,786 --> 01:12:58,755 하지만 ImageNet과 다소 다르게 생긴 데이터셋을 가지고있다면 문제가 될 수 있습니다. 699 01:12:58,755 --> 01:13:06,781 가령 X-rays나 CAT scans와 같은 의료영상들은 대게 ImageNet의 데이터와는 많이 다릅니다. 700 01:13:06,781 --> 01:13:09,072 이 경우에는 좀 더 창의적인 방법이 필요할 수 있습니다. 701 01:13:09,072 --> 01:13:14,408 기존의 전략이 잘 동작할 수도 있겠지만 어쩌면 최종 레이어만 학습시키는 전략이 쓸모없어 질 수도 있을 것입니다. 702 01:13:14,408 --> 01:13:21,507 어쩌면 네트워크의 더 많은 부분은 다시 초기화시켜야 하거나 하는 더 창의적이고 경험적인 부분이 필요합니다. 703 01:13:21,507 --> 01:13:29,015 다만 이 문제는 여러분의 데이터셋이 아주 크다면 조금 완화됩니다. 이 경우에는 더 많은 레이어를 fine-tune 해 볼수 있기 때문이죠 704 01:13:29,015 --> 01:13:32,587 한가지 말씀드리고 싶은 것은 transfer learning이 아주 보편적이라는 것입니다. 705 01:13:32,587 --> 01:13:35,660 사실 transfer learning은 거의 일상적인 수준이 되었습니다. 706 01:13:35,660 --> 01:13:40,562 Computer vision 관련 논문들을 읽어보면 다양한 task에 대한 다음과 같은 시스템 다이어그램을 보실 수 있을 것입니다. 707 01:13:40,562 --> 01:13:44,706 왼쪽은 Object Detection과 관련된 다이어그램입니다. 오른쪽은 Image Captioning과 관련된 것이죠 708 01:13:44,706 --> 01:13:48,387 두 모델 모두 CNN구조를 가지고 있고 기본적으로 이미지를 처리합니다. 709 01:13:48,387 --> 01:13:53,913 요즘에는 거의 모든 computer vision 관련 응용 알고리즘들이 모델들을 밑바닥부터(from scrtch) 학습시키지 않습니다. 710 01:13:53,913 --> 01:13:59,973 대부분은 ImageNet pretrained-model을 사용하고 현재 본인의 task에 맞도록 fine tune 합니다. 711 01:13:59,973 --> 01:14:07,089 captioning의 경우 word vectors를 pretrain하기도 합니다. 712 01:14:07,089 --> 01:14:14,143 pretrained CNN 뿐만 아니라 규모가 큰 말뭉치로부터 학습된 pretrained word vectors도 함께 이용할 수 있겠습니다. 713 01:14:14,143 --> 01:14:22,278 captioning task에서는 pretrained word vectors을 사용하는 경우가 그닥 많지 않고 크게 중요하지 않습니다. 714 01:14:22,278 --> 01:14:33,225 여러분에게 어떤 문제가 있는데 이 문제에 대한 데이터셋이 크지 않은 경우라면 715 01:14:33,225 --> 01:14:41,673 우선 여러분의 task와 유사한 데이터셋으로 학습된 pretrained model 다운로드 받습니다. 716 01:14:41,673 --> 01:14:44,859 그리고 이 모델의 일부를 초기화시키고 여러분 데이터로 모델을 fine-tune 합니다. 717 01:14:44,859 --> 01:14:50,676 여러분의 Training data가 적당히만 있다면 아마 아주 잘 동작할 것입니다. 718 01:14:50,676 --> 01:14:57,738 이런 경우가 너무 흔하기 때문에 대부분의 딥러닝 소프트웨어 패키지들은 model zoo를 제공합니다. 719 01:14:57,738 --> 01:15:01,099 단지 접속만 하면 다양한 모델들의 pretrained 버전을 손쉽게 다운로드 받을 수 있습니다. 720 01:15:01,099 --> 01:15:06,043 오늘 한 내용을 요약해 보자면 우선 optimization을 배웠습니다. training loss를 개선하는 방법이었죠. 721 01:15:06,043 --> 01:15:10,884 regularization에 대해서도 배웠습니다. test data에서의 성능을 향상시키는 방법이었습니다. 722 01:15:10,884 --> 01:15:12,838 Model ensembling도 regularization에 속했었죠 723 01:15:12,838 --> 01:15:17,440 그리고 transfer learning에 대해서도 배웠습니다. 데이터가 적을때 할 수 있는 아주 좋은 방법이었습니다. 724 01:15:17,440 --> 01:15:21,940 이들은 모두 아주 좋은 방법들입니다. 여러분들의 프로젝트 등에 사용해야만 하는 것들입니다. 725 01:15:21,940 --> 01:15:25,238 다음 시간에는 다양한 딥러닝 소프트웨어 패키지들이 대해서 조금 더 자세히 배워보도록 하겠습니다.